diff --git a/README.md b/README.md index f3c9b88..d13c0a2 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,21 @@ When a commit is pushed to the `main` branch (e.g., when a pull request merges), 1. Open `team-members/.csv` 1. Add a new line of the form `,`, where `` should be `member`. +### Give someone runner management or merge-queue bypass without making them an org owner? + +Add them to the `infrastructure` team (`team-members/infrastructure.csv`). That team: + +- Holds GitHub's predefined **CI/CD admin** organization role, granting management of + org self-hosted runners and runner groups (plus Actions policies, secrets, variables, + and usage metrics). See `organization.tf`. +- Is a ruleset bypass actor on `osac` and `osac-test-infra`, so its members can bypass + the merge queue and required status checks on those repos. See `ruleset_bypass_team_ids` + in `repositories.tf`. + +The broader `wg-infra` working group keeps the narrower `runner-manager` role and the same +bypass; `infrastructure` is a smaller team for people who need this without the rest of the +working-group context. + ### Add a new repository? 1. Open `repositories.tf` diff --git a/organization.tf b/organization.tf index 823502d..d96a590 100644 --- a/organization.tf +++ b/organization.tf @@ -27,3 +27,29 @@ resource "github_organization_role_team" "runner_manager_wg_infra" { role_id = github_organization_role.runner_manager.role_id team_slug = github_team.all["wg-infra"].slug } + +# Assign GitHub's predefined "CI/CD admin" organization role to the infrastructure +# team. It grants admin access to Actions policies, runners, runner groups, hosted +# compute network configs, secrets, variables, and usage metrics for the org -- a +# superset of the runner-manager role above -- without granting org-owner access. +data "github_organization_roles" "all" {} + +locals { + # Predefined roles are returned with source = "Predefined". The API's exact + # spelling for this role's `name` isn't documented (GitHub's own docs example + # for the analogous "security manager" role uses the slug "security_manager"), + # so match the known spellings exactly rather than with a loose regex. If the + # lookup comes back empty, get the real value and pin role_id directly: + # gh api /orgs/osac-project/organization-roles --jq '.roles[] | select(.source=="Predefined") | {id, name}' + cicd_admin_role_names = ["CI/CD admin", "cicd_admin", "ci_cd_admin"] + + cicd_admin_role_id = one([ + for r in data.github_organization_roles.all.roles : r.id + if r.source == "Predefined" && contains(local.cicd_admin_role_names, r.name) + ]) +} + +resource "github_organization_role_team" "cicd_admin_infrastructure" { + role_id = local.cicd_admin_role_id + team_slug = github_team.all["infrastructure"].slug +} diff --git a/repositories.tf b/repositories.tf index 5939ae7..eb30388 100644 --- a/repositories.tf +++ b/repositories.tf @@ -142,6 +142,10 @@ module "repo_osac" { { team_id = "wg-infra" permission = "admin" + }, + { + team_id = "infrastructure" + permission = "push" } ] # Prow plugins handle approval via OWNERS (lgtm/approved labels), not native @@ -184,7 +188,10 @@ module "repo_osac" { { context = "Run unit tests (osac-operator)", integration_id = 15368 }, { context = "Run unit tests (bare-metal-fulfillment-operator)", integration_id = 15368 }, ] - ruleset_bypass_team_ids = [github_team.all["wg-infra"].id] + ruleset_bypass_team_ids = [ + github_team.all["wg-infra"].id, + github_team.all["infrastructure"].id, + ] merge_queue = { merge_method = "SQUASH" @@ -328,6 +335,10 @@ module "repo_osac_test_infra" { { team_id = "wg-infra" permission = "admin" + }, + { + team_id = "infrastructure" + permission = "push" } ] required_approvals = null @@ -341,8 +352,11 @@ module "repo_osac_test_infra" { # check_response_timeout_minutes for a check that never reports. { context = "pre-commit", integration_id = 15368 }, ] - ruleset_bypass_team_ids = [github_team.all["wg-infra"].id] - environments = [{ name = "e2e-test" }] + ruleset_bypass_team_ids = [ + github_team.all["wg-infra"].id, + github_team.all["infrastructure"].id, + ] + environments = [{ name = "e2e-test" }] merge_queue = { merge_method = "SQUASH" diff --git a/team-members/infrastructure.csv b/team-members/infrastructure.csv new file mode 100644 index 0000000..127ebee --- /dev/null +++ b/team-members/infrastructure.csv @@ -0,0 +1,3 @@ +username,role +omer-vishlitzky,member +minmzzhang,member diff --git a/teams.csv b/teams.csv index 9fe720a..4a619a3 100644 --- a/teams.csv +++ b/teams.csv @@ -5,3 +5,4 @@ observability-wg,observability working group,secret personas-wg,Personas working group,secret documentation-wg,Documentation working group,secret wg-infra,OSAC Infrastructure working group,closed +infrastructure,Infrastructure & CI/CD operations - runners and merge-queue bypass,closed