feat: switch to label-driven releases with workflow_dispatch escape hatch#160
feat: switch to label-driven releases with workflow_dispatch escape hatch#160kevwilliams merged 7 commits intomainfrom
Conversation
| bump-type: | ||
| description: "Version bump type" | ||
| type: choice | ||
| options: [patch, minor, major] | ||
| default: patch |
There was a problem hiding this comment.
Maybe it's better to have the release version as an input and the workflow orchestrating this is the thing responsible for determining the version to create?
There was a problem hiding this comment.
its effectively a shortcut for adding the release: label which gives less room for error and is only here for situations like when someone forgets to add the release:patch label to the PR before merging it and needs to run it.
There was a problem hiding this comment.
I just meant that maybe the release version should be an input to this pipeline and not have the npm job be responsible for determining the release version. Ideally that's done by whatever is calling this repo since that version number needs to be consistent across many steps.
There was a problem hiding this comment.
ok good call ive rearchitected this a bit more along these lines, it still has a job that does it but the publish-npm-job now just does build and publish
new flow looks like this
push to main (with release label) or workflow_dispatch
│
├── detect-mode → release-mode, bump-type
│
├── bump-version → npm version patch/minor/major
│ owns: git commit + tag + push to main
│ outputs: new-version (e.g. v0.3.2)
│
├── publish → checkout main (already has bumped package.json)
│ reusable workflow: build + npm publish only, no git ops
│
└── create-release → gh release create v0.3.2
depends on: bump-version output (not publish) ```
There was a problem hiding this comment.
Wonder if we should have this be a manually triggered workflow? What if we want to merge in multiple features to a single release before pushing out.
There was a problem hiding this comment.
Sure we can remove the label detection and just stick with workflow_dispatch as the release trigger
- Add bump-version job: owns npm version, git tag, and push to main - The publish job receives the version already set in package.json - The create-release job depends on bump-version output, not publish - Remove bump-type pass-through to reusable workflow (no longer needed) - The reusable workflow now only builds and publishes
Every push to main publishes a dev build. Stable releases are triggered explicitly via workflow_dispatch, allowing multiple PRs to be batched into a single release before shipping.
| # Runs only on manual dispatch. Bumps the version in package.json, commits, | ||
| # creates the git tag, and pushes to main. All downstream jobs read the | ||
| # version from this job's output — the npm publish workflow receives it | ||
| # already set in package.json. | ||
| bump-version: | ||
| name: Bump version | ||
| if: github.event_name == 'workflow_dispatch' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| outputs: | ||
| new-version: ${{ steps.bump.outputs.new-version }} | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: main | ||
|
|
||
| - name: Setup pnpm | ||
| uses: pnpm/action-setup@v4 | ||
| with: | ||
| package_json_file: ui/package.json | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 24 | ||
| cache: pnpm | ||
| cache-dependency-path: ui/pnpm-lock.yaml | ||
|
|
||
| - name: Configure git | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
|
|
||
| - name: Bump version and push tag | ||
| id: bump | ||
| working-directory: ui | ||
| env: | ||
| BUMP_TYPE: ${{ inputs.bump-type }} | ||
| run: | | ||
| if [[ "$BUMP_TYPE" != "major" && "$BUMP_TYPE" != "minor" && "$BUMP_TYPE" != "patch" ]]; then | ||
| echo "::error::Invalid bump-type '$BUMP_TYPE'. Must be major, minor, or patch." | ||
| exit 1 | ||
| fi | ||
| NEW_VERSION=$(npm version "$BUMP_TYPE" \ | ||
| --message "chore: release @datum-cloud/activity-ui v%s [skip ci]") | ||
| echo "new-version=${NEW_VERSION}" >> "$GITHUB_OUTPUT" | ||
| git push origin main --follow-tags |
There was a problem hiding this comment.
Thoughts on moving this to the shared actions repo as a bump-npm-version job? Seems valuable to re-use across repos. Can we also have a separate step that takes the bump type and turns it into the version that's being released? Want to de-couple those concepts since the npm workflow shouldn't be responsible for determining what the next version should be.
There was a problem hiding this comment.
Done — moved to datum-cloud/actions as a new bump-npm-version.yaml reusable workflow (added to PR #59 there). The workflow has two distinct steps: resolve-version computes the new version string from package.json + bump-type using inline Node.js (no git ops), then bump-version runs npm version + git push. The new-version output is set from the resolve step so callers get the version string independently of the git operations.
publish-ui-npm.yaml here is now just a 5-line uses: call that passes package-path, package-name, and bump-type — no more inline steps.
…#59) ## Summary - Removes version bumping, git tagging, and PR label detection from \`publish-npm-package\`'s \`publish-release\` job — it now only builds and publishes whatever version is already in \`package.json\` - Removes GitHub Release creation from \`publish-npm-package\` — callers are responsible for this - Adds a new \`bump-npm-version.yaml\` reusable workflow that owns the full version bump lifecycle: 1. **resolve-version** — computes the new version string from \`package.json\` + \`bump-type\` using inline Node.js (no git ops); outputs \`new-version\` (e.g. \`v1.3.0\`) 2. **bump** — runs \`npm version\`, creates the commit and tag 3. **push** — \`git push origin main --follow-tags\` ## Motivation The previous \`publish-release\` job did too much: it detected bump type from PR labels, bumped the version, pushed the tag, built, and published — all in one job. This made it hard to reuse across repos and coupled version calculation to the publish step. The new design separates concerns: - **bump-npm-version** owns the git side (version resolution → commit → tag → push) - **publish-npm-package** owns the npm side (build → publish) Callers compose them as sequential jobs, passing \`new-version\` between them. The resolved version is available as an output before any git operations run. ## Dependency \`datum-cloud/activity\` PR #160 references \`v1.13.0\` of both \`bump-npm-version.yaml\` and \`publish-npm-package.yaml\` — this PR should be merged and tagged \`v1.13.0\` first. ## Test plan - [ ] Merge this PR and cut tag \`v1.13.0\` - [ ] Merge datum-cloud/activity#160 which references \`v1.13.0\` - [ ] Trigger \`workflow_dispatch\` on activity with \`bump-type=minor\` → confirm minor bump commit, tag, npm publish, and GitHub Release all created correctly - [ ] Push to activity main without dispatch → confirm only dev build published, no release created
## Summary `bump-npm-version.yaml` never runs `pnpm install`, so `setup-node` with `cache: pnpm` fails at teardown because the cache directory doesn't exist: ``` Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved. ``` This caused the `Post Setup Node.js` step to fail in datum-cloud/activity#160. ## Changes - Remove `pnpm/action-setup` step — not needed when there's no install - Remove `cache: pnpm` and `cache-dependency-path` from `setup-node` — same reason - Remove `lockfile-path` input — only existed to support pnpm caching The workflow only needs Node.js to read `package.json` (version resolution) and run `npm version` (bump + tag). ## Test plan - [ ] Merge and tag `v1.13.1` - [ ] Re-run the failing workflow in datum-cloud/activity — `Post Setup Node.js` should no longer fail
Fixes the `Post Setup Node.js` cache failure introduced in #160. `bump-npm-version.yaml` never runs `pnpm install`, so `setup-node` with `cache: pnpm` failed at teardown because the cache directory didn't exist. datum-cloud/actions#60 removed the pnpm cache from that workflow and was released as `v1.13.1`. ## Test plan - [ ] Trigger `workflow_dispatch` on this branch → `Post Setup Node.js` no longer fails
Summary
release: publishedtrigger (was the source of the circular tag problem)workflow_dispatchtrigger withbump-typeinput (patch/minor/major) as an escape hatch for "I forgot to add the label"detect-modejob that reads the merged PR's labels to decide dev vs release modebump-typethrough to the reusable workflow soworkflow_dispatchworks without a PR to read labels fromHow releases work now
Normal flow (merge with label):
release,release:minor, orrelease:majorlabel to the PR before mergingmain— CI detects the label, runs in release mode, bumps version, tags, publishes to npm, creates GitHub ReleaseForgot the label (escape hatch):
No label (default):
x.y.z-dev.{sha}) to the@devnpm dist-tag onlyDependency
Requires
datum-cloud/actionsdatum-cloud/actions#59 to be merged and tagged asv1.13.0first — this workflow references that version.Test plan
v1.13.0@v1.13.0reference in this file once that tag existsrelease:minorlabel → confirm minor version bump + GH Releaseworkflow_dispatchwithmajor→ confirm major bump + GH Release