diff --git a/.gds/bundle.lock.yaml b/.gds/bundle.lock.yaml index 0d1209a..931b8b5 100644 --- a/.gds/bundle.lock.yaml +++ b/.gds/bundle.lock.yaml @@ -5,16 +5,16 @@ bundle: version: "0.4.0-dev" release_sequence: 0 channel: "development" - source_commit: "b6ec1c5fec0d8a3cfe2f2a137345b76881d8f11d" - digest: "sha256:9bbe6b84da6f459eb508510ad41fdb33cd199e54c3925b34bf95201e4543fe59" + source_commit: "216d21e2c701338aeb6315c5ff6626056da4419d" + digest: "sha256:81c5d2fc786ce255ab303c9453d38bc3e75bcf98a61785f9b1a2fa8e786499c1" projection: - input_digest: "sha256:3f8712b1e5cba6324a3a6ce53ff33c87ca4d768d9cfbe7336a64d78aa7699e33" - output_digest: "sha256:9cdcbe11b96f88ea2cb883bec396f14653751570402da44f9b33ed0fc06ea442" + input_digest: "sha256:d1940e8848e700984c5889ecc542bc3f66753eefa4d84c2aef1fdcbc57a9b15e" + output_digest: "sha256:691dd0550a3f3a80447df5fe2e991d12f91b8b88f8e4d6aadadd0b7703c9ddcb" files: - path: ".claude/CLAUDE.md" digest: "sha256:7b50d15feae7b63b94d845b2fa6e19e3220527c5b0cac69303b7fc19bd7484a8" - path: ".gds/compiled-policy.json" - digest: "sha256:9e887c3b6d68dd8d1aa293792a6528e1655050eaf2b46bfb1c3032c9dc1bf0bf" + digest: "sha256:eb993e8d0c9c09139b6b3c91e7c1dd9500d6268ca57ac73d1417611b73d9aeb6" - path: "AGENTS.md" digest: "sha256:37a41633f771e7a95804071538e67836c47c36a142237a2fb8097297b34113d8" diff --git a/.gds/compiled-policy.json b/.gds/compiled-policy.json index 8463742..28f72a8 100644 --- a/.gds/compiled-policy.json +++ b/.gds/compiled-policy.json @@ -3,7 +3,7 @@ "compiled_policy": { "repository_id": "repo_01KYFBZ4AK44Y9B7MRQ1C2WKPF", "bundle_version": "0.4.0-dev", - "digest": "sha256:920596f87d0175bfbb373f1c3d21b6a92eab9dcca881f65c8c72a536a961e68b" + "digest": "sha256:cd81c5467b74b96161d8710ae010f7c7a4a35bac9f3c1663236f71ebc4ed007f" }, "sources": [ { @@ -12,7 +12,7 @@ "priority": 100, "distribution": "public", "path": "policies/base/repository-default.yaml", - "digest": "sha256:13324a48e45daa7008310bb24d158ee92b606316040e3a70433b5c942a187af5" + "digest": "sha256:538f486d49620c169cbbac77745ce2ecc21010ebd4a564017c79cefbb468ca1e" }, { "id": "organization-default", @@ -28,7 +28,7 @@ "priority": 100, "distribution": "public", "path": "policies/roles/public-module.yaml", - "digest": "sha256:ece6164691eda262e2692f97bd70262ea98c268084900b3f285f3d50f3767200" + "digest": "sha256:084f7b09dbfd85a386e47cf83ea0015154b6b01fa3cf85a68f04ef407b89ed4b" } ], "effective": { @@ -103,6 +103,12 @@ "value": "PR_TITLE" } }, + "releases": { + "immutable": { + "management": "managed", + "value": true + } + }, "rulesets": { "management": "observed" }, @@ -364,6 +370,20 @@ "file": "policies/base/repository-default.yaml", "operation": "set" }, + "/effective/github/releases/immutable/management": { + "source": "public-module", + "tier": "role", + "priority": 100, + "file": "policies/roles/public-module.yaml", + "operation": "set" + }, + "/effective/github/releases/immutable/value": { + "source": "public-module", + "tier": "role", + "priority": 100, + "file": "policies/roles/public-module.yaml", + "operation": "set" + }, "/effective/github/rulesets/management": { "source": "repository-default", "tier": "base", diff --git a/.gds/repository.yaml b/.gds/repository.yaml index 2c43a0d..459cd1f 100644 --- a/.gds/repository.yaml +++ b/.gds/repository.yaml @@ -52,3 +52,4 @@ module: github_release: "required" release: mode: "github-release" + tag_style: "semver" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..bfa3200 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,25 @@ +name: test + +on: + pull_request: + branches: [main] + push: + branches: [main] + +permissions: + contents: read + +concurrency: + group: test-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: test + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - name: Check out exact source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Validate public contracts + run: python3 cli-tools/validate_public_contracts.py diff --git a/cli-tools/validate_public_contracts.py b/cli-tools/validate_public_contracts.py index 749c2f9..66ff153 100755 --- a/cli-tools/validate_public_contracts.py +++ b/cli-tools/validate_public_contracts.py @@ -628,8 +628,30 @@ def check_provider_protocol( "cli-tools/provider_runtime_v3.py", ): check_text(relative, errors) - if (ROOT / ".github/workflows").exists(): - errors.append("public Actions workflows are forbidden") + workflows = ROOT / ".github" / "workflows" + if not workflows.is_dir(): + errors.append("required release-check workflow directory is missing") + else: + workflow_files = {path.name for path in workflows.iterdir() if path.is_file()} + if workflow_files != {"test.yml"}: + errors.append("public repository may contain only the release-check test.yml workflow") + else: + workflow = (workflows / "test.yml").read_text(encoding="utf-8") + for fragment in ( + "permissions:\n contents: read", + "runs-on: ubuntu-24.04", + "name: test", + "actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1", + "run: python3 cli-tools/validate_public_contracts.py", + ): + if fragment not in workflow: + errors.append( + f"test.yml is missing required release-check fragment: {fragment!r}" + ) + if "pull_request_target" in workflow or "${{ secrets" in workflow: + errors.append( + "test.yml may not use privileged PR triggers or repository secrets" + ) def main() -> int: