Overview
Two complete GitHub Actions workflows for a repo that ownsshipd.config.ts. flags-diff previews flag changes on every pull request that touches the file. flags-push applies them when the change merges to main. Each authenticates with its own service account token (shipd_sa_…), so pull request jobs can read flags but never change them, and both handle the CLI’s exit codes explicitly.
What’s in it
@shipdit/cliis a dev dependency, so CI runs the same CLI version as your machine.flags-diff.ymlrunsshipd diff --exit-code, writes the plan to the job summary, and checks thatsrc/generated/flags.tsis committed.flags-push.ymlrunsshipd push --ciand turns exit codes into errors or warnings.- Both jobs target project
web-app, environmentproduction.
Set up the tokens
-
In the dashboard, go to Settings → Service accounts and click Create service account. Name it
github-actions. -
Open the account and click Create token twice, binding both to project
web-app(not to an environment). Scopes match an exact action, soflag:updatedoes not grantflag:read:Addflag:archiveto the push token only if you push with--prune. See Sync flags in CI for the reasoning. - Copy each token. They are shown once.
- In GitHub, go to Settings → Secrets and variables → Actions and add both as repository secrets.
Files
package.json
pnpm/action-setup reads the pnpm version from packageManager.
shipd.config.ts
.github/workflows/flags-diff.yml
.github/workflows/flags-push.yml
Exit codes
The full list lives in the CLI reference.
Run it
shipd.config.ts. The flags-diff job summary shows the plan. Merge it and flags-push applies the plan to production.
Adapt it
- To block pull requests on any drift, including changes someone made in the dashboard, make exit code
2fail: replace itscaseline withexit 2. - To fail the push job while an approval is pending, make exit code
5fail the same way. - For more environments, copy the push job and change
SHIPD_ENV.defaultvalues apply per environment. Definition fields apply to the whole project. SHIPD_API_URLis required in CI. Onlyshipd loginfalls back tohttps://api.useshipd.com. You can also setapiUrlin.shipd/config.json.- Secrets are not passed to workflows triggered from forks, so
flags-difffails there. Skip the job for forks withif: github.event.pull_request.head.repo.full_name == github.repository. - Use
--pruneonly after you confirm that no one manages flags in this project outsideshipd.config.ts. It archives remote-only flags.