Skip to content
10 changes: 6 additions & 4 deletions deploy/organization-rulesets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ verb — e.g. `require-pull-request.yaml`). Repo-scoped rulesets live next door
| `require-signed-commits.yaml` | **Require signed commits** (existing, retired) | Observe + Update — retain the disabled record; never create or delete |
| `protect-release-tags.yaml` | **Protect release tags** (net-new) | Managed (Create) — block tag delete + force-move + require `v<semver>` |
| `require-world-at-ruin-trusted-regressions.yaml` | **Require workflow - World at Ruin trusted regressions** (net-new) | Managed (Create) — target only World at Ruin and require the canonical catalogue's trusted regression workflow |
| `require-world-at-ruin-product-regressions.yaml` | **Require workflow - World at Ruin product regressions** (net-new) | Managed (Create) — target only World at Ruin and require its product-owned trusted regression workflow from reviewed `main` |
| `require-monorepo-ci-aggregate-contract.yaml` | **Require workflow - Monorepo CI aggregate contract** (net-new) | Managed (Create) — target only monorepo and require the aggregate-execution control from its reviewed `main` |
| `require-dotgithub-deploy-guards.yaml` | **Require workflow - .github deploy guards** (net-new) | Managed (Create) — target only this repository and run the `deploy/` release-contract and deletion validators from its reviewed `main` |
| `require-go-template-validation.yaml` | **Require workflow - Go template validation** (net-new) | Managed (Create) — target only go-template and require the canonical Go validation workflow from this repository's reviewed `main`, restoring the gate the property-conditioned UI ruleset stopped applying there |
Expand Down Expand Up @@ -113,10 +114,11 @@ gates; a team audit cannot clear the latter two.
that file's header for the team-vs-enterprise tier caveat on the name-pattern rule and
its fallback.
- **Required-workflow source pins** — v0.20.0 exposes the source repository, path and a
branch/tag `ref`, but not GitHub's immutable workflow `sha` selector. The World at Ruin
rule therefore binds the external trusted source to `devantler-tech/.github` on
`refs/heads/main`; Actions review and merge gates own source changes until the provider
exposes `sha`.
branch/tag `ref`, but not GitHub's immutable workflow `sha` selector. The two World at
Ruin rules bind the established external source in `devantler-tech/.github` and the
product-owned replacement in `devantler-tech/world-at-ruin` independently to
`refs/heads/main`. Their separate rulesets preserve replacement enforcement while the
established rule is later disabled and retired.
- **Actions policies** — the 2026-06-18
[workflow execution protections](https://github.blog/changelog/2026-06-18-control-who-and-what-triggers-github-actions-workflows/)
(actor + event allow-lists controlling who/what triggers workflows, delivered as org
Expand Down
1 change: 1 addition & 0 deletions deploy/organization-rulesets/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ resources:
# Net-new, managed (Create).
- protect-release-tags.yaml
- require-world-at-ruin-trusted-regressions.yaml
- require-world-at-ruin-product-regressions.yaml
- require-monorepo-ci-aggregate-contract.yaml
- require-dotgithub-deploy-guards.yaml
- require-go-template-validation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Require World at Ruin's product-owned regression workflow on the product's
# default branch. This rule is separate from the established external rule so
# the replacement remains active while that rule is disabled and retired.
#
# GitHub selects the workflow from World at Ruin's reviewed main branch rather
# than from candidate bytes. provider-upjet-github v0.20.0 exposes a branch/tag
# ref but not GitHub's workflow SHA selector, so refs/heads/main is the strongest
# declarative source binding the deployed provider can express.
#
# This is net-new and managed Observe + Create + Update + LateInitialize, never
# Delete. No bypassActors are declared.
apiVersion: enterprise.github.m.upbound.io/v1alpha1
kind: OrganizationRuleset
metadata:
name: require-world-at-ruin-product-regressions
spec:
managementPolicies:
- Observe
- Create
- Update
- LateInitialize
forProvider:
name: Require workflow - World at Ruin product regressions
target: branch
enforcement: active
conditions:
- refName:
- include: ["~DEFAULT_BRANCH"]
exclude: []
repositoryId: [1303188705]
rules:
- requiredWorkflows:
- requiredWorkflow:
- repositoryId: 1303188705
path: .github/workflows/trusted-regressions.yaml
ref: refs/heads/main
providerConfigRef:
kind: ProviderConfig
name: default
27 changes: 23 additions & 4 deletions tests/world-at-ruin-regression-ruleset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,36 @@ assert_value "source repository" "933213756" '.spec.forProvider.rules[0].require
assert_value "source path" ".github/workflows/world-at-ruin-required-regressions.yaml" '.spec.forProvider.rules[0].requiredWorkflows[0].requiredWorkflow[0].path'
assert_value "source ref" "refs/heads/main" '.spec.forProvider.rules[0].requiredWorkflows[0].requiredWorkflow[0].ref'

selector='select(.kind == "OrganizationRuleset" and .metadata.name == "require-world-at-ruin-product-regressions")'
count="$(yq -N "${selector} | .metadata.name" "${render}" | grep -c . || true)"
[[ "${count}" == "1" ]] || fail "expected exactly one rendered product-regression ruleset, got ${count}"

assert_value "product ruleset name" "Require workflow - World at Ruin product regressions" '.spec.forProvider.name'
assert_value "product ruleset target" "branch" '.spec.forProvider.target'
assert_value "product ruleset enforcement" "active" '.spec.forProvider.enforcement'
assert_json "product management policy" '["Observe","Create","Update","LateInitialize"]' '.spec.managementPolicies'
assert_json "product target repository" '[1303188705]' '.spec.forProvider.conditions[0].repositoryId'
assert_json "product target branch" '["~DEFAULT_BRANCH"]' '.spec.forProvider.conditions[0].refName[0].include'
assert_json "product target exclusions" '[]' '.spec.forProvider.conditions[0].refName[0].exclude'
assert_value "product bypass actor count" "0" '(.spec.forProvider.bypassActors // []) | length'
assert_value "product rule count" "1" '.spec.forProvider.rules | length'
assert_value "product required workflow block count" "1" '.spec.forProvider.rules[0].requiredWorkflows | length'
assert_value "product required workflow count" "1" '.spec.forProvider.rules[0].requiredWorkflows[0].requiredWorkflow | length'
assert_value "product source repository" "1303188705" '.spec.forProvider.rules[0].requiredWorkflows[0].requiredWorkflow[0].repositoryId'
assert_value "product source path" ".github/workflows/trusted-regressions.yaml" '.spec.forProvider.rules[0].requiredWorkflows[0].requiredWorkflow[0].path'
assert_value "product source ref" "refs/heads/main" '.spec.forProvider.rules[0].requiredWorkflows[0].requiredWorkflow[0].ref'

inventory="${repo_root}/deploy/organization-rulesets/README.md"
grep -Fq 'The 10 imported org rulesets' "${inventory}" ||
fail "organization ruleset inventory must account for 10 imported rulesets"
# The backticks are literal Markdown table cell delimiters, not command substitution.
# shellcheck disable=SC2016
managed_rows="$(grep -c '^| `[a-z-]*\.yaml` | .*(net-new) | Managed (Create)' "${inventory}" || true)"
[[ "${managed_rows}" == "5" ]] ||
fail "organization ruleset inventory must list 5 managed rulesets, got ${managed_rows}"
[[ "${managed_rows}" == "6" ]] ||
fail "organization ruleset inventory must list 6 managed rulesets, got ${managed_rows}"
managed_rendered="$(yq -N 'select(.kind == "OrganizationRuleset" and (.spec.managementPolicies | contains(["Create"]))) | .metadata.name' "${render}" | grep -c . || true)"
[[ "${managed_rendered}" == "5" ]] ||
fail "expected 5 rendered managed (Create) organization rulesets, got ${managed_rendered}"
[[ "${managed_rendered}" == "6" ]] ||
fail "expected 6 rendered managed (Create) organization rulesets, got ${managed_rendered}"
# Schema inspection is not a live census. Keep rendered ownership checks above,
# and require the capability inventory to preserve that evidence boundary.
if ! grep -Fq 'Schema support determines what can be declared; it does not prove adoption,' "${inventory}" ||
Expand Down
Loading