Skip to content

ci: bind the release deployment environment to main - #3287

Merged
Astro-Han merged 1 commit into
mainfrom
ci/release-env-branch-policy
Aug 20, 2026
Merged

ci: bind the release deployment environment to main#3287
Astro-Han merged 1 commit into
mainfrom
ci/release-env-branch-policy

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

The release GitHub Environment holds the Apple notarization and code signing credentials that .github/workflows/release-desktop.yml consumes, and it currently has no protection rules at all. Nothing outside the workflow constrains which ref may deploy with those credentials.

The workflow does carry a job-level branch condition, but that condition lives in the same file it is meant to protect, so it cannot serve as the boundary for the environment's secrets. The boundary that holds regardless of the workflow file is the environment's own deployment branch policy, which GitHub evaluates before a job that requests the environment starts.

This declares that policy in .asf.yaml, restricting release to main. npm-release already carries the same kind of policy, so this reuses an established pattern in this repository rather than introducing a new one.

npm-release is deliberately left undeclared. The asfyaml directive only visits the environments it is given, so npm-release and copilot are untouched — but the underlying API call replaces an environment's settings wholesale, so naming npm-release here without restating its existing reviewer and branch policy would clear them. The .asf.yaml comment records that constraint where the next editor will see it.

Verification

Validated against the upstream asfyaml implementation at apache/infrastructure-asfyaml@main, not against documentation. All of the below was re-run after the final wording of the .asf.yaml comment:

  • asfyaml.cli:validate on this branch's checkout — reports the file as valid. Negative control: renaming deployment_branch_policy to a key not in the schema makes the same run fail with unexpected key not in schema, confirming the new block actually reaches ASFGitHubFeature.schema. Note for anyone tempted to wire this into CI: validate() prints the error but still exits 0, so it would need an explicit output check to work as a gate.
  • _validate_environment_configs from asfyaml/feature/github/deployment_environments.py on the parsed environments map — no errors. The parsed value is exactly {"release": {"deployment_branch_policy": {"policies": [{"name": "main", "type": "branch"}], "protected_branches": false}}}.
  • Reproduced asfyaml's two-stage parse (dirty_load of the whole file, then dirty_load of github.as_yaml()) to confirm the comment block does not pollute the folded description scalar: 184 characters before and after the round trip, identical. yaml.safe_load does not exercise this path.
  • Confirmed the existing protected_branches.main.required_status_checks.contexts still parses as ['test'] after the round trip.

Not run: repository test suites, lint and typecheck. This change touches only .asf.yaml, which no workspace suite covers and which Biome does not format.

Rollout

ASF Infrastructure applies .asf.yaml on push to the default branch, so the policy takes effect on merge. Applying it issues a full environment update for release, which also writes asfyaml's defaults of wait_timer: 0 and prevent_self_review: true. The environment currently has no reviewers, no wait timer and no branch policy, so nothing existing is cleared and prevent_self_review is a no-op until a reviewer is ever added. Environment secrets live on a separate endpoint and are not affected. In-flight runs are not affected.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code (Opus 5) read the upstream asfyaml source to confirm the schema and directive semantics, wrote the .asf.yaml change, ran the validation described above, and drafted this description. A second pass by Claude Code (Fable 5) adversarially reviewed the change and independently reproduced each verification step above; its findings corrected the comment wording and prompted the scope section. Both are AI review and neither substitutes for independent human review. The commit carries a Generated-by trailer. A human contributor reviews the final diff and owns the merge decision.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Neither applies: there is no test hook for .asf.yaml, and Biome does not cover YAML. Validation against the upstream schema and directive is described above.

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

This is a security hardening change to a protected area, so it is not a self-merge candidate and needs independent human review.

@Astro-Han
Astro-Han force-pushed the ci/release-env-branch-policy branch from 375d4fe to d6d05f8 Compare August 20, 2026 06:13
The release environment holds the Apple notarization and code signing
credentials that .github/workflows/release-desktop.yml consumes, but it
carries no protection rules at all. Its only current guard is the job-level
branch condition inside release-desktop.yml, which lives in the same file it
is meant to protect and so cannot bind the environment on its own.

Declare a deployment branch policy that restricts the environment to main.
GitHub enforces it outside the workflow, before any job that requests the
environment starts. npm-release already carries the same kind of policy, so
this reuses an established pattern rather than inventing one.

The directive only visits environments named here, so npm-release and
copilot keep their current configuration. npm-release is deliberately left
undeclared: the underlying call replaces an environment's settings
wholesale, and declaring it without restating its reviewer and branch
policy would clear them.

Generated-by: Claude Code
@Astro-Han
Astro-Han force-pushed the ci/release-env-branch-policy branch from d6d05f8 to 51572ff Compare August 20, 2026 06:25
@Astro-Han
Astro-Han marked this pull request as ready for review August 20, 2026 06:31
@Astro-Han
Astro-Han requested review from M4n5ter and hqhq1025 August 20, 2026 07:09
@Astro-Han

Copy link
Copy Markdown
Contributor Author

Requesting review from @M4n5ter and @hqhq1025.

@M4n5ter — this applies the environment protection pattern from #3192 to the desktop signing channel. npm-release got a branch policy there; release never got one. Two things worth your eye: whether a custom branch policy pinned to main matches what you intended for npm-release, and whether stopping at the branch boundary is the right scope here. Adding required_reviewers to release is deliberately left out — any committer releasing from main is the model we want, so the two channels intentionally end up with the same branch boundary and different approval boundaries.

@hqhq1025 — mainly the CI and release-path side: whether pinning release to main breaks any dispatch path we actually use.

On validation: the schema and directive semantics were checked against the upstream apache/infrastructure-asfyaml source rather than its documentation, including a negative control confirming the new block actually reaches ASFGitHubFeature.schema. .asf.yaml has no CI coverage in this repo, so that manual check is the only verification — worth a skeptical pass.

This touches release credentials, so it is not a self-merge candidate.

@hqhq1025 hqhq1025 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No actionable findings.

Problem and mechanism

The release GitHub Environment contains five Apple signing and notarization
secrets, but its live configuration currently has no deployment protection
rules. The workflow checks github.ref itself, which a collaborator could
remove in a branch copy before dispatching that branch.

This PR adds an environment-owned custom branch policy for the exact main
branch. GitHub evaluates that policy before the build matrix jobs can start
and access the environment secrets.

Evidence and first-principles assessment

  • The live release environment has no reviewers, timer, or branch policy, so
    the asfyaml full update does not erase existing protection.
  • Upstream infrastructure-asfyaml validates this shape and emits
    protected_branches=false, custom_branch_policies=true, with one
    { name: "main", type: "branch" } policy.
  • The directive iterates only named environments, so npm-release and
    copilot are not modified.
  • Environment secrets are managed through a separate endpoint and are not part
    of this update.
  • Every observed desktop release workflow run and deployment used main, so
    the policy preserves the established release path.
  • The PR merges cleanly onto current main, and required CI is green.

The problem definition and solution follow first principles and Occam's razor:
the credential owner should enforce its own admissible refs, and one exact
environment policy is the smallest mechanism that does so.

Deletion, tests, and architecture

There is no production code or low-value test to delete. No deeper refactor is
needed. The existing workflow-level main checks remain useful defense in
depth, while the environment policy becomes the external credential boundary.

Merge verdict

Approved at 51572ff281e5f8615a9b56c995babb30856db512.

Residual operational checks:

  • After merge and ASF Infrastructure application, verify through the GitHub API
    that release reports custom branch policies enabled with exactly the
    main branch policy and that the five environment secret names remain.
  • release currently allows repository administrators to bypass environment
    protection. This PR correctly protects ordinary write collaborators; if the
    project also wants to remove the administrator break-glass path, that setting
    needs a separate manual change or upstream asfyaml support.

@Astro-Han
Astro-Han merged commit 3db43c2 into main Aug 20, 2026
1 check passed
@Astro-Han
Astro-Han deleted the ci/release-env-branch-policy branch August 20, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants