Release, provenance, and rollback
Lycato releases are built only by the protected release workflow.
It runs the repository's canonical ci:release plan once, seals the compiled packages and public
Hosting tree as a commit-addressed artifact, and allows publication or deployment only after that job
passes. Local commands are useful rehearsals, not an alternate production release path.
One-time environment setup
Create two protected GitHub environments with required reviewers and deployment-branch/tag rules:
npm-productionfor package publication. StoreNPM_TOKENthere until every package uses npm trusted publishing; the job also grants only the OIDCid-token: writepermission needed for npm provenance.firebase-productionfor Firebase. ConfigureGCP_WORKLOAD_IDENTITY_PROVIDERandGCP_FIREBASE_SERVICE_ACCOUNTfor a Google service account restricted to Auth-provider deployment, Firestore/Storage rule publication, and thelycatoprodHosting target. The environment URL ishttps://lycato.app; usedocs/deployment/PRODUCTION_DOMAIN.mdfor Firebase/Cloudflare validation. Do not store a service-account JSON key or Firebase refresh token.
Both workflows default to contents: read, use commit-pinned actions, disable checkout credential
persistence, pin pnpm 11.1.1, bound every job with a timeout, and serialize releases by Git ref.
Cut a release
- Add a changeset for every publishable package whose behavior changed.
- On a release branch, run
pnpm exec changeset version, thenpnpm install --lockfile-onlyso package versions, internal dependency ranges, changelogs, and the lockfile move together. - Run
pnpm run ci:release. Review the package manifests and generated changelogs, then merge the version commit tomain. - Create and push a new signed
v*tag at that exact commit. Never move or reuse a release tag. - Approve the
npm-productionandfirebase-productionjobs after the verification job is green.
The npm job downloads the compiled outputs from the verified job and runs Changesets with
NPM_CONFIG_PROVENANCE=true. The Firebase job downloads the same verified artifact, reruns the public
tree allowlist/link check, authenticates with short-lived Workload Identity Federation credentials,
and deploys Auth providers, Firestore/Storage rules, and Hosting without rebuilding.
firebase.json intentionally has no predeploy build hook: a build at deployment time would replace
the artifact that passed the release gate.
After publication, confirm the npm registry shows provenance for each new version and that package
metadata links to https://github.com/axysar/lycato. Confirm the Firebase release points at the
expected Git commit and run the public Hosting smoke check against production before announcing it.
Roll back safely
Published npm versions are immutable. Do not unpublish a normal bad release and never overwrite its tag. Instead:
- deprecate each affected version with a precise warning;
- move the
latestdist-tag back to the last known-good version if new installs are unsafe; - fix forward, add changesets, and publish a new patch version through the protected workflow.
For Hosting, select the last known-good release in Firebase Hosting's release history and use its rollback control, then rerun the production smoke check. Keep the failed GitHub artifact and CI summary for diagnosis. Correct the source and deploy a newly verified artifact; do not rebuild or edit the rolled-back artifact in place.
If package and Hosting behavior must remain coupled, roll back Hosting first (the reversible edge), restore safe npm dist-tags second, and then ship a coordinated forward fix. Record the affected versions, artifact SHA, operator, timestamps, and verification result in the incident or release log.