diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1e44365 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +charset = utf-8 + +[*.{md,tf}] +indent_style = space +indent_size = 2 + +[justfile] +indent_style = space +indent_size = 4 diff --git a/.github/images/repository-access-all-repositories.png b/.github/images/repository-access-all-repositories.png new file mode 100644 index 0000000..603551f Binary files /dev/null and b/.github/images/repository-access-all-repositories.png differ diff --git a/.github/images/repository-permissions-issues-read-and-write.png b/.github/images/repository-permissions-issues-read-and-write.png new file mode 100644 index 0000000..cc659fc Binary files /dev/null and b/.github/images/repository-permissions-issues-read-and-write.png differ diff --git a/.github/images/resource-owner.png b/.github/images/resource-owner.png new file mode 100644 index 0000000..99af9c7 Binary files /dev/null and b/.github/images/resource-owner.png differ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..6b96bd9 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,45 @@ +# Copyright 2025 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: CI +on: + workflow_call: + pull_request: + +jobs: + inclusive-naming-check: + name: Inclusive naming check + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Run tests + uses: get-woke/woke-action@v0 + with: + fail-on-error: true + + validation: + name: Validate Terraform plans + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install `opentofu` + run: sudo snap install opentofu --classic + - name: Install `just` + uses: extractions/setup-just@v2 + with: + just-version: 1.38.0 + - name: Run validation tests + run: just validate diff --git a/.github/workflows/update-org-labels.yaml b/.github/workflows/update-org-labels.yaml new file mode 100644 index 0000000..479bd7c --- /dev/null +++ b/.github/workflows/update-org-labels.yaml @@ -0,0 +1,42 @@ +# Copyright 2025 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: Update Charmed HPC organization labels +on: + workflow_call: + push: + branches: + - main + +jobs: + ci: + uses: ./.github/workflows/ci.yaml + + update-org-labels: + name: Update Charmed HPC organization labels + needs: + - ci + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install `opentofu` + run: sudo snap install opentofu --classic + - name: Install `just` + uses: extractions/setup-just@v2 + with: + just-version: 1.38.0 + - name: Update organization labels + run: | + CHARMED_HPC_ORG_PAT="${{ secrets.LABELS_TOKEN }}" just apply labels diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bcc5fc3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea +.vscode +.terraform +.terraform.lock.hcl +*.tfstate* diff --git a/justfile b/justfile new file mode 100755 index 0000000..3548b98 --- /dev/null +++ b/justfile @@ -0,0 +1,73 @@ +#!/usr/bin/env just --justfile +# Copyright 2025 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Necessary to use `||` logical operator. +set unstable := true + +terraform_dir := justfile_dir() + "/terraform/" +default_plan_list := shell("ls -d -- $1/*", terraform_dir) + +[private] +default: + @just help + +# Initialize Terraform plans +[group("terraform")] +init *plans: + #!/usr/bin/env bash + set -euxo pipefail + plans=({{ prepend(terraform_dir, plans) || default_plan_list }}) + for plan in ${plans[@]}; do + tofu -chdir=${plan} init + done + +# Validate Terraform plans +[group("terraform")] +validate *plans: (init plans) + #!/usr/bin/env bash + set -euxo pipefail + plans=({{ prepend(terraform_dir, plans) || default_plan_list }}) + for plan in ${plans}; do + tofu -chdir=${plan} fmt -check + tofu -chdir=${plan} validate + done + +# Apply Terraform plans +[group("terraform")] +apply *plans: (validate plans) + #!/usr/bin/env bash + set -euxo pipefail + plans=({{ prepend(terraform_dir, plans) || default_plan_list }}) + for plan in ${plans[@]}; do + tofu -chdir=${plan} plan + GITHUB_TOKEN=${CHARMED_HPC_ORG_PAT} tofu -chdir=${plan} apply -auto-approve + done + +# Apply formatting standards to project +[group("dev")] +fmt: + just --fmt --unstable + tofu fmt -recursive + +# Clean project directory +[group("dev")] +clean: + find . -name .terraform -type d | xargs rm -rf + find . -name .terraform.lock.hcl -type f | xargs rm -rf + find . -name "terraform.tfstate*" -type f | xargs rm -rf + +# Show available recipes +help: + @just --list --unsorted diff --git a/terraform/labels/README.md b/terraform/labels/README.md new file mode 100644 index 0000000..0c418e9 --- /dev/null +++ b/terraform/labels/README.md @@ -0,0 +1,90 @@ +# `labels` Terraform plan + +This is a Terraform plan for managing labels in the Charmed HPC GitHub organization using the +GitHub Terraform provider. For more information, refer to the +[documentation](https://registry.terraform.io/providers/integrations/github/latest/docs) +for the GitHub Terraform provider. + +## Requirements + +This plan requires that you have a GitHub Personal Access Token (PAT) that grants organization-wide +permissions to edit issue and pull request labels. Refer to the [usage](#usage) section for more details. + +## Managed organization repositories + +Below is the list of Charmed HPC organization repositories whose labels are managed by the +`labels` Terraform plan: + +* .github +* docs +* charmed-hpc-terraform +* hpc-libs +* slurm-charms +* slurm-snap +* slurmutils +* filesystem-charms +* ondemand-snap + +To add a new repository to the `labels` plan, add the repository's name +to the default set declared by the `repository` variable in [_variables.tf_](./variables.tf). Note +that the `labels` plan will fail with the 422 HTTP error code if the newly added repository already +has a label with the same name as a label defined in the plan. + +## Created labels + +| Name | Color code | Description | Tag can be used to classify... | +|--------------------|------------|-----------------------------------------------------------------------------------------|------------------------------------| +| blocked | 57006f | A dependency issue must be resolved before this is actionable | Issues, pull requests | +| C-filesystem | a54a05 | Component: Filesystem (charms, libraries, packaging, etc.) | Pull requests, issues, discussions | +| C-idm | a54a06 | Component: Identity Management (charms, libraries, packaging, etc.) | Pull requests, issues, discussions | +| C-slurm | a54a04 | Component: Slurm (charms, libraries, packaging, etc.) | Pull requests, issues, discussions | +| C-terraform | a54a07 | Component: Terraform/OpenTofu (charm modules, product modules, etc.) | Pull requests, issues, discussions | +| cleanup | 16cc3b | This pull request cleans up the project and introduces no functional changes | Pull requests | +| confirmed | 99eac1 | This issue was successfully reproduced during triage | Issues | +| docs | 2f7cdc | This pull request makes a change to the documentation | Pull requests | +| feature | 466334 | This pull request adds a new feature to the project | Pull requests | +| fix | ca299e | This pull request fixes a confirmed issue | Pull requests | +| good first issue | 7ff5e8 | Good first issue for project newcomers | Issues | +| help wanted | afddc7 | This issue needs an assignee | Issues | +| needs testing | 18ef6b | This pull request needs additional tests added before it is eligible for merge | Pull requests | +| needs triage | b04642 | Reported issue needs to be confirmed the triage | Issues | +| P-critical | c70c78 | Priority: Issue needs addressed as soon as possible | Issues | +| P-high | c65103 | Priority: Issue needs addressed within a two week pulse | Issues | +| P-low | a0cab4 | Priority: Issue should be addressed within a six month cycle | Issues | +| P-medium | 3df315 | Priority: Issue needs addressed within a month | Issues | +| R-cannot-reproduce | dc9b13 | Resolution: This issue could not be reproduced during triage | Issues, discussions | +| R-duplicate | dc9b13 | Resolution: This issue or pull request is a duplicate | Issues, discussions | +| R-needs-more-info | dc9b11 | Resolution: This issue needs additional information provided before triage can continue | Issues, discussions | +| R-out-of-scope | dc9b12 | Resolution: This issue or pull request is out-of-scope for project | Issues, discussions | +| ux | 3b33d1 | This pull request changes the user experience of the project | Pull requests | + +## Usage + +To add the labels to the organization repositories, first generate a Personal Access Token (PAT) with permission +to edit Issue/Pull Request labels. You can generate a PAT by navigating in GitHub to Settings > Developer +settings > Personal access tokens > Fine-grained tokens and then select ___Generate new token___. + +From the ___Generate new token___ page, provide a token name and then set the `charmed-hpc` GitHub organization +as the resource owner: + +![Resource owner dropdown on Generate new token page with the `charmed-hpc` GitHub organization set as the owner](../../.github/images/resource-owner.png) + +After setting `charmed-hpc` as the resource owner, now set the repository access +to all repositories: + +!["All repositories" radio button selected for repository access permission level](../../.github/images/repository-access-all-repositories.png) + +Now set the repository permissions for _Issues_ to __Read and write__: + +![Repository permissions for Issues with Access dropdown set to "Read and write"](../../.github/images/repository-permissions-issues-read-and-write.png) + +With all the PAT options set, generate the token and copy it to your clipboard. + +Now, run the `just apply` recipe with the following command, passing your +newly generated PAT as an environment variable: + +```shell +CHARMED_HPC_ORG_PAT= just apply labels +``` + +After a few minutes, Terraform should complete updating the all the given repository labels. diff --git a/terraform/labels/main.tf b/terraform/labels/main.tf new file mode 100644 index 0000000..3fc5731 --- /dev/null +++ b/terraform/labels/main.tf @@ -0,0 +1,31 @@ +# Copyright 2025 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +provider "github" { + owner = "charmed-hpc" +} + +resource "github_issue_labels" "charmed-hpc-project-repos" { + for_each = var.repository + repository = each.value + + dynamic "label" { + for_each = var.label + content { + name = label.value["name"] + color = label.value["color"] + description = label.value["description"] + } + } +} diff --git a/terraform/labels/variables.tf b/terraform/labels/variables.tf new file mode 100644 index 0000000..64a2939 --- /dev/null +++ b/terraform/labels/variables.tf @@ -0,0 +1,151 @@ +# Copyright 2025 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +variable "label" { + description = "Labels for Charmed HPC project repositories" + type = list(map(string)) + default = [ + { + name = "blocked" + color = "57006f" + description = "A dependency must be resolved before this is actionable" + }, + { + name = "C-filesystem" + color = "a54a05" + description = "Component: Filesystem" + }, + { + name = "C-idm" + color = "a54a06" + description = "Component: Identity Management" + }, + { + name = "C-slurm" + color = "a54a04" + description = "Component: Slurm" + }, + { + name = "C-terraform" + color = "a54a07" + description = "Component: Terraform/OpenTofu" + }, + { + name = "cleanup" + color = "16cc3b" + description = "This pull request cleans up the project and introduces no functional changes" + }, + { + name = "confirmed" + color = "99eac1" + description = "This issue was successfully reproduced during triage" + }, + { + name = "docs" + color = "2f7cdc" + description = "This pull request makes a change to the documentation" + }, + { + name = "feature" + color = "466334" + description = "This pull request adds a new feature to the project" + }, + { + name = "fix" + color = "ca299e" + description = "This pull request fixes a confirmed issue" + }, + { + name = "good first issue" + color = "7ff5e8" + description = "Good first issue for project newcomers" + }, + { + name = "help wanted" + color = "afddc7" + description = "This issue needs an assignee" + }, + { + name = "needs testing" + color = "18ef6b" + description = "This pull request needs additional tests added before it is eligible for merge" + }, + { + name = "needs triage" + color = "b04642" + description = "Reported issue needs to be confirmed the triage" + }, + { + name = "P-critical" + color = "c70c78" + description = "Priority: Issue needs addressed as soon as possible" + }, + { + name = "P-high" + color = "c65103" + description = "Priority: Issue needs addressed within a two week pulse" + }, + { + name = "P-low" + color = "a0cab4" + description = "Priority: Issue should be addressed within a six month cycle" + }, + { + name = "P-medium" + color = "3df315" + description = "Priority: Issue needs addressed within a month" + }, + { + name = "R-cannot-reproduce" + color = "dc9b13" + description = "Resolution: This issue could not be reproduced during triage" + }, + { + name = "R-duplicate" + color = "dc9b13" + description = "Resolution: This issue or pull request is a duplicate" + }, + { + name = "R-needs-more-info" + color = "dc9b11" + description = "Resolution: This issue needs additional information provided before triage can continue" + }, + { + name = "R-out-of-scope" + color = "dc9b12" + description = "Resolution: This issue or pull request is out-of-scope for project" + }, + { + name = "ux" + color = "3b33d1" + description = "This pull request changes the user experience of the project" + } + ] +} + +variable "repository" { + description = "List of Charmed HPC repositories to apply labels to" + type = set(string) + default = [ + ".github", + "docs", + "charmed-hpc-terraform", + "hpc-libs", + "slurm-charms", + "slurm-snap", + "slurmutils", + "filesystem-charms", + "ondemand-snap", + ] +} diff --git a/terraform/labels/versions.tf b/terraform/labels/versions.tf new file mode 100644 index 0000000..6475928 --- /dev/null +++ b/terraform/labels/versions.tf @@ -0,0 +1,22 @@ +# Copyright 2025 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +terraform { + required_providers { + github = { + source = "integrations/github" + version = "~> 6.0" + } + } +}