CI/CD & Releases¶
Maintainer reference for GitHub Actions, secrets, and how to ship a version of leash-secrets.
Not Fork Shepherd. Fork Shepherd is a Marketplace action for forks syncing with an upstream. This page is about leash-secrets’s own pipelines. The Release Draft workflow only reuses the same release idea (manual patch/minor/major → draft → publish).
Mental model¶
You open a PR
→ CI (+ Validate Patterns if patterns change)
→ merge when green
Push lands on main
→ CI again
→ Deploy Docs (if docs/** changed)
→ Validate Patterns (if patterns/** changed)
→ Release (release-please) ← legacy; usually ignore
When you want to ship a version
→ Actions → Release Draft (patch/minor/major)
→ workflow bumps version files + pushes commit (if needed)
→ draft GitHub Release appears
→ you Publish the draft in the UI
→ Publish npm runs (skips if that version is already on npm)
| Stage | Tool | Output |
|---|---|---|
| Validate code | CI | Pass/fail on PR |
| Update docs site | Deploy Docs | GitHub Pages |
| Cut a version | Release Draft | Version bump commit (if needed) + draft GitHub Release + assets |
| Make it live | You click Publish | Public GitHub Release |
| Package registry | Publish npm | leash-secrets on npm (no-op if already published) |
Workflow table¶
| Workflow | When it runs | Purpose |
|---|---|---|
| CI | Every PR + every push to main (+ manual) | Quality gate: Node 18/20/22 tests, shell syntax, hygiene (incl. install.sh ↔ package.json version), dogfood scan |
| Validate Patterns | PRs/pushes that touch patterns/ (or related tests/scripts) | Pattern JSON / fixture validation |
| Deploy Docs | Push to main that touches docs/** (or MkDocs config) (+ manual) | MkDocs → GitHub Pages |
| Release (release-please) | Push to main (+ manual) | Legacy. Tries to manage release PRs/tags. Org often blocks Actions from opening PRs — prefer Release Draft |
| Release Draft | Manual (workflow_dispatch) | You pick patch/minor/major → bumps version files if needed → draft leash-secrets-vX.Y.Z + assets |
| Publish npm | Manual, or when a draft release is published | npm publish --provenance (succeeds as no-op if version already on npm) |
Workflow files live under .github/workflows/.
After a merge to main — what runs, in order¶
Merging a PR (or landing a commit on main) does not publish npm. These workflows fire automatically from the push:
| Order | Workflow | Runs when? | What it does | You should… |
|---|---|---|---|---|
| 1 | CI | Always on push to main | Re-runs the full test matrix on main | Wait for green. Required status check for future PRs. |
| 2 | Validate Patterns | Only if the merge touched patterns/**, tests/**, or scripts/check-patterns.js | Extra pattern/fixture checks | Confirm green if it ran; otherwise ignore. |
| 3 | Deploy Docs | Only if the merge touched docs/**, mkdocs.yml, requirements.txt, or the docs workflow | Builds MkDocs and deploys GitHub Pages | Confirm the site updated if you changed docs. |
| 4 | Release (release-please) | Always on push to main | Legacy release-please attempt | Ignore unless debugging. Prefer Release Draft to ship. |
Nothing else is required for a normal feature/fix merge.
When you want to ship a version (manual, after main is green)¶
Do these in order — they are not automatic on merge:
| Order | Action | Workflow / UI | Purpose |
|---|---|---|---|
| 1 | Run Release Draft | Actions → Release Draft → patch/minor/major | Bumps version on main (needs org GitHub App; see below), creates draft leash-secrets-vX.Y.Z |
| 2 | Review & Publish the draft | Releases → open draft → Publish | Makes the GitHub Release public; fires the next step |
| 3 | Publish npm | Runs automatically on publish (or Actions → Publish npm) | Publishes leash-secrets@X.Y.Z (skips if already on npm) |
Optional: Publish npm alone if the GitHub release/tag already exists and you only need the registry.
Secrets needed¶
Prefer org-level secrets (FasterApiWeb → Settings → Secrets and variables → Actions → Organization secrets) so nothing is tied to a personal account. Grant them to leash-secrets (and any other repos that release the same way).
| Secret | Required? | Used by | How to create |
|---|---|---|---|
NPM_TOKEN | Yes (to publish) | Publish npm | npmjs.com → Access Tokens → Granular token with Read and Write + Bypass 2FA for publish |
RELEASE_APP_ID / RELEASE_APP_PRIVATE_KEY / RELEASE_APP_INSTALLATION_ID | Recommended | Release Draft | Org GitHub App (see below). Preferred over a personal PAT. |
RELEASE_TOKEN | Avoid | Release Draft | Personal PAT — not needed if the App is configured |
VSCE_PAT | Deferred | VS Code extension publish | Azure DevOps PAT with Marketplace → Manage |
Org GitHub App for Release Draft (recommended)¶
GITHUB_TOKEN cannot push to protected main. A personal RELEASE_TOKEN works but is tied to one human. Use an org-owned GitHub App instead. No workflow file changes are required — release-draft.yml already reads these secrets.
1. Create the App (org owner)¶
- Open github.com/organizations/FasterApiWeb/settings/apps/new
- Fill in:
- GitHub App name: e.g.
FasterApiWeb Release(must be unique on GitHub) - Homepage URL:
https://github.com/FasterApiWeb(or this repo’s URL) - Webhook: uncheck Active
- Repository permissions:
- Contents → Read and write
- Metadata → Read-only (usually already set)
- Leave Account permissions at No access
- Where can this GitHub App be installed? → Only on this account
- Click Create GitHub App
2. Generate the private key¶
- On the App settings page → Private keys → Generate a private key
- Download the
.pem(paste into a secret once; never commit it) - Note the App ID under About (digits only)
3. Install the App on the org¶
- App settings → Install App (or open the App’s install URL)
- Choose FasterApiWeb
- Only select repositories →
leash-secrets(or all repos if you reuse it) - Install
4. Copy the Installation ID¶
- Org → Settings → GitHub Apps → Installed GitHub Apps → Configure next to the App
- URL looks like:
https://github.com/organizations/FasterApiWeb/settings/installations/XXXXXXXX
XXXXXXXX=RELEASE_APP_INSTALLATION_ID
5. Add org Actions secrets¶
- Organization secrets → New organization secret for each:
| Name | Value |
|---|---|
RELEASE_APP_ID | App ID (number) |
RELEASE_APP_PRIVATE_KEY | Full .pem contents (including BEGIN / END lines) |
RELEASE_APP_INSTALLATION_ID | Installation ID (number) |
- Repository access → Selected repositories → add
leash-secrets
Do not add a personal RELEASE_TOKEN if the App is configured.
6. Bypass rulesets for the App (required)¶
Secrets alone are not enough — branch rules still block pushes unless the App is on the bypass list.
- Repo Rules (or org rulesets) → open the ruleset that targets
main - Bypass list → Add bypass → GitHub Apps → select your Release App
- Bypass mode: Always allow (or Exempt)
- Save
Also check classic Settings → Branches protection if it still applies.
7. Actions policy¶
Org or repo: Settings → Actions → General → Allow all actions and reusable workflows
(needed for actions/create-github-app-token@v2)
8. Verify¶
- Actions → Release Draft → Run workflow (
main,patch; optionaldry_runfirst) - Log step Resolve release token should say:
Using GitHub App installation token - On a real run, the bump commit should land on
main(notrelease/v*)
Release Draft token preference: App → RELEASE_TOKEN → GITHUB_TOKEN.
Day-to-day (features / fixes)¶
- Open a PR → wait for CI (and Validate Patterns if you changed patterns).
- Merge when green (squash).
- On
main: CI always; Deploy Docs / Validate Patterns only if paths match; ignore Release. - No npm publish on normal merges.
How to ship a version¶
1. Create a draft release¶
- Actions → Release Draft → Run workflow
- Branch:
main - Bump:
patch/minor/major - Optional:
dry_run= true to preview the next tag
The workflow:
- Computes the next version from the latest
leash-secrets-v*tag - If
package.jsonis behind, bumpspackage.json,install.sh,CITATION.cff,vscode-extension/package.json, manifest, andCHANGELOG.md, then pusheschore: release X.Y.Ztomain - Creates a draft release
leash-secrets-vX.Y.Z+ assets
If the push fails (branch protection), finish the org GitHub App + ruleset bypass steps above, then re-run. Without that, the workflow falls back to a release/vX.Y.Z branch (merge that to main manually, then delete the branch).
2. Publish the draft¶
- Releases → open the draft
- Review notes/assets
- Publish release
Result: Publish npm runs and publishes leash-secrets@X.Y.Z (or no-ops if that version is already on npm).
3. If you only need npm¶
Actions → Publish npm → Run workflow — publishes whatever version is on the checked-out ref; skips cleanly if already published.
Optional local prep (still supported): bash scripts/prepare-release.sh if you prefer a version-bump PR before Release Draft.
Branch protection (maintainer note)¶
main requires PRs and the CI status checks. Required approving reviews are set to 0 so the sole maintainer can merge their own PRs (GitHub never counts self-approvals). CI must still be green. Revisit if more maintainers join.
See also: CONTRIBUTING.md (repo root) and Development Setup.