Repository navigation
Conversation
There was a problem hiding this comment.
Scoping the secrets to environments and moving permissions down to the jobs both look right. The production/release split in deploy*.yml is sensible, and the GITHUB_TOKEN reductions hold up: the pushes use the App token, publish-vscode only uploads, and the GHCR push gets packages: write at job level. I only reviewed the YAML; the settings and merge-order steps can't be checked from here.
Public API: unchanged. Only CI workflows and CODEOWNERS change.
Concerns:
- Approval gate on every
devrun. #58885 and #58898 addedreleaseas the place where versioned releases wait for approval, and their comments say dev previews skip that wait. This PR makesreleaseunconditional for publish (version, build-cli, sign-cli-macos, publish), deploy, deploy-files, deploy-www, deploy-changelog and nix-hashes on everydevpush. It does the same for the scheduledmodels-snapshotandstatsjobs. Ifreleasestill has required reviewers, all of those will wait for a human every time. The settings section doesn't say to remove the reviewer, and doing so would drop the manual gate on versioned releases. Either state that the reviewer goes away, or keep a separate approval-gated environment, used conditionally as before, for the versioned-release path (see inline). - CODEOWNERS gaps (inline):
packages/desktop/scripts/andsdks/vscode/script/also run inreleasewith signing and publishing secrets, but/packages/*/script/doesn't cover them.
| if: github.repository == 'anomalyco/opencode' | ||
| # Versioned releases wait for approval in the release environment, which only allows dev. | ||
| environment: ${{ (inputs.bump || inputs.version) && 'release' || '' }} | ||
| environment: release |
There was a problem hiding this comment.
This used to be (inputs.bump || inputs.version) && 'release' || '', and #58885 described release as the step where versioned releases wait for approval. With release unconditional here and on build-cli, sign-cli-macos, publish, the deploy* jobs, nix-hashes, models-snapshot and stats, every dev push and every scheduled run will wait for a reviewer if one is still configured on release. Could the description say whether the required reviewer is being removed? If the manual gate on versioned releases should stay, you could use a second environment holding the same secrets, with the reviewer, and apply it only to version/publish when needs.version.outputs.release is set.
| # CI, release, and publish scripts | ||
| /.github/ @anomalyco/ci-owners | ||
| /script/ @anomalyco/ci-owners | ||
| /packages/*/script/ @anomalyco/ci-owners |
There was a problem hiding this comment.
/packages/*/script/ doesn't match packages/desktop/scripts/, whose prepare.ts and publish.ts run in build-electron and publish with the Apple, Azure and Tauri signing secrets. It also doesn't match sdks/vscode/script/, which runs with VSCE_PAT. packages/desktop/scripts/ still falls under the existing packages/desktop/ rule (Hona and Brendonovich only). If this file is meant to gate every script that runs in release, those two paths need entries too.
|
Removed |
There was a problem hiding this comment.
The new commit only deletes publish-vscode.yml. My two earlier threads stay open. The approval gate on release hasn't been addressed. Deleting the workflow takes care of the sdks/vscode/script/ half of the CODEOWNERS thread, but packages/desktop/scripts/ still isn't covered.
Public API: unchanged (CI only).
With the workflow gone, nothing publishes the VS Code extension anymore. sdks/vscode/script/release still pushes vscode-v* tags, but those tags no longer trigger anything, and sdks/vscode/script/publish is no longer called. If ending extension releases is intended, those scripts can go too. If not, the extension needs another way to publish. The description also still lists publish-vscode, VSCE_PAT/OPENVSX_TOKEN and the vscode-v* tag in the release policy, so the settings steps should be updated to match.
|
Folded into #59046, which includes both commits from this PR (secrets scoped to the release environment, and the VS Code workflow removal) plus the build/publish split. |
Issue for this PR
Release-path hardening requested by Dax (security finding 319).
Type of change
What does this PR do?
This PR moves every CI job that reads a secret into one GitHub environment,
release, which only allowsdevandbeta. Once the repo-level secrets are moved into that environment and deleted, no other branch can run a job that reads them.GITHUB_TOKEN, or needsid-token: write, and runs on push todev/beta, on a schedule, or fromworkflow_dispatchnow declaresenvironment: releaseunconditionally. That covers npm publish, signing, AUR, Homebrew, WinGet, Discord and Cloudflare. No jobs are split.publish.yml, the conditional environment onversionand onpublishis replaced with plainenvironment: release.productionbranch keep using the existingproductionenvironment (branchproduction, reviewer thdxr). Merging it intoreleasewould let anydevpush readSTRIPE_SECRET_KEY_PRODand assume the production AWS role, whose trust is bound toenvironment:production.permissionsinpublish.ymldrop tocontents: read. Job-level grants are added only where needed:id-token: writefor Azure OIDC and npm trusted publishing,packages: writefor the GHCR push. The same treatment applies todeploy.yml,containers.yml,models-snapshot.yml,nix-hashes.yml,notify-discord.ymlandpublish-vscode.yml.models-snapshotandnix-hashespush with the GitHub App token, so they don't needcontents: writeonGITHUB_TOKEN..github/CODEOWNERSgains@anomalyco/ci-ownerson/.github/,/script/,/packages/*/script/and/github/. The existing app/desktop entries are kept.Job → environment → secrets
release(dev, beta) /production(production) (+ id-token)release/productionvscode-v*vscode-v*)release: released(tag ref)github-v*, dispatchgithub/**)PR-triggered workflows: secrets that stay repo-level
check,test,storybook,nix-eval(pull_request), pluspr-management,pr-standards(pull_request_target), pluscompliance-close,close-issues,close-prs(schedule) use no repo-level secrets. They only useGITHUB_TOKEN, and the repo default token permission isread. Nothing high-risk has to stay at repo level, so every secret can move.Settings changes needed (not applied by this PR)
1. Create in the
releaseenvironment (secrets):OPENCODE_APP_SECRET, OPENCODE_API_KEY, APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORD, APPLE_API_KEY, APPLE_API_KEY_PATH, APPLE_API_ISSUER, AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID, AZURE_TRUSTED_SIGNING_ACCOUNT_NAME, AZURE_TRUSTED_SIGNING_CERTIFICATE_PROFILE, AZURE_TRUSTED_SIGNING_ENDPOINT, SENTRY_AUTH_TOKEN, AUR_KEY, TAURI_SIGNING_PRIVATE_KEY, TAURI_SIGNING_PRIVATE_KEY_PASSWORD, WINGET_GITHUB_TOKEN, CLOUDFLARE_API_TOKEN, DISCORD_WEBHOOK, VSCE_PAT, OPENVSX_TOKEN, POSTHOG_KEY, PLANETSCALE_SERVICE_TOKEN, PLANETSCALE_SERVICE_TOKEN_NAME, STRIPE_SECRET_KEY_DEV
…and variable: AWS_DEPLOY_ROLE_ARN (the dev role ARN, copied from the
devenvironment).OPENVSX_TOKENdoesn't exist at repo, org or environment level today, so the OpenVSX step ofpublish-vscodealready fails.AUR_KEYis currently an org secret. Move it, then remove this repo's access to the org secret.2. Add to the
productionenvironment (secrets): CLOUDFLARE_API_TOKEN, PLANETSCALE_SERVICE_TOKEN, PLANETSCALE_SERVICE_TOKEN_NAME, STRIPE_SECRET_KEY_PROD, SENTRY_AUTH_TOKEN. It already has AWS_DEPLOY_ROLE_ARN. Prefer separate, narrower Cloudflare, PlanetScale and Sentry tokens from thereleaseones.3. AWS: add
repo:anomalyco/opencode:environment:releaseto thesublist of IAM roleopencode-dev-github-actions-deploy(account 438095551154). It is currentlyenvironment:devonly. Removeenvironment:devafter this PR merges. Don't touch the production role; it staysenvironment:production.4. Environment policies:
release: keep branchesdevandbetaand tagvscode-v*. Proposed: add tagv*only ifnotify-discord.ymlis still wanted. It fires onrelease: released, whose ref is the tag, andv*tags are limited to ci-owners by ruleset. Otherwise deletenotify-discord.yml; V2 announces frompublish.yml. Don't addproductiontorelease, for the reason given above. The existingproductionenvironment already covers production deploys.beta,v1,copilotandstaging - packages/docsenvironments have no branch policy, so any branch can use them. None of them holds secrets today. Delete them, or restrictbetatobeta. Thedevenvironment can be deleted once step 3 is done. ItsENTERPRISE_SALES_INBOX_EMAILsecret isn't referenced by any workflow, and neither is the copy inproduction.v1branch is unprotected, and its ownpublish.yml(ci: gate v1 releases behind the release environment #58899) gates v1 releases onrelease. Sincev1was removed from thereleasepolicy, v1 versioned releases can't get secrets. That is the intended outcome. If v1 releases are still needed, the safe option is a separatev1-releaseenvironment with a required reviewer, plus a ruleset that restrictsv1to ci-owners.5. npm trusted publishers: set environment
releaseon the trusted publisher of every packagescript/publish.tspublishes: the@opencode/*packages schema, codemode, theme, ai, util, protocol, client, cli and its platform packages, cli-node and its platform packages, plugin, plugin-browser, core, simulation, server, sdk, ui. Theopencode-aipackages are published from thev1branch; see thev1note above.6. Azure federated credential: change the subject to
repo:anomalyco/opencode:environment:release. Today's jobs run without an environment, so the token subject isrepo:anomalyco/opencode:ref:refs/heads/dev(orbeta). With an environment it becomesenvironment:release, so the old credential stops matching on the first run after merge.7. Repo secrets no workflow on
devreferences (delete candidates): APPLE_ID, APPLE_PASSWORD, BRENDAN_GITHUB_TOKEN, DISCORD_ISSUES_WEBHOOK_URL, KEYCHAIN_PASSWORD, PORTER_APP_18525_975734319, SIGNPATH_API_KEY, SIGNPATH_ARTIFACT_CONFIGURATION_SLUG, SIGNPATH_ORGANIZATION_ID, SIGNPATH_PROJECT_SLUG, SIGNPATH_SIGNING_POLICY_SLUG.Merge order
Every reference is a plain
secrets.NAME. GitHub resolves environment secrets first, then repo, then org, so until a repo or org secret is deleted the jobs keep finding it. The PR is therefore safe to merge before secrets move, except for three things that must be ready first:environment:release), add the AWS_DEPLOY_ROLE_ARN variable torelease(step 1), and add the second Azure federated credential (step 6, keeping the old one). Do steps 5 and 2 too: npm OIDC fails without the environment claim, andproductiondeploys need their secrets once the repo copies are gone. Without step 3, the nextdevdeploy can't assume the AWS role. Variables don't fall back the way secrets do:AWS_DEPLOY_ROLE_ARNexists only in thedevandproductionenvironments.devpush ofpublish,deployanddeploy-*.releaseandproduction(steps 1 and 2).AUR_KEY. Only after this step is the goal met: until then, any branch can push a workflow that reads repo secrets directly.Known side effect, not fixed here: the GitHub App and rulesets
script/publish.tspushesrefs/tags/vX.Y.ZandHEAD:devusing the OpenCode GitHub App token (opencode-agent, app id 1549082).models-snapshotandnix-hashesalso push todevwith it.publish-github-actionandrelease-github-actionpushlatestandgithub-v*tags withGITHUB_TOKEN.v*,vscode-v*,github-v*) bypasses only team ci-owners. The app is a bypass actor on "release tags (thdxr only)", but every matching ruleset must pass, so the release tag push is blocked.release-github-actioncreatinggithub-v*tags is blocked too.sync release versionscommit and the bot commits frommodels-snapshotandnix-hashes.Proposal: add Integration 1549082 as a bypass actor on the "Release tags: ci-owners only" ruleset only. The app's private key lives only in the
releaseenvironment, so after step 4 onlydev/betajobs can mint that token. Fordev, either add the app as a bypass on the dev ruleset (the bot commits are generated files), or have those jobs open PRs. For thegithub-v*tags, moverelease-github-actionandpublish-github-actionto the app token withenvironment: release.How did you verify your code works?
actionlint1.7 (-ignore runner-label) reports only the existingif: falsewarning indocs-locale-sync.yml.GITHUB_TOKENsecret or needingid-token: writedeclares an environment.devpush after merge is the real test.Checklist