Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ name: Release (CLI + Web bundle)
# The native desktop GUI app ships on a separate, experimental pre-release
# track — see .github/workflows/release-gui.yml.
#
# Pushing a version tag does everything: build, Evidence Pack, provenance,
# the GitHub Release, and the npm publish. There is no manual publish step —
# npm previously drifted from the tags because that step was done by hand.
#
# Recommended flow:
# 1. Run manually (workflow_dispatch) → download + inspect the artifacts.
# 2. When satisfied, push the version tag to publish:
# 1. Bump the version in BOTH package.json and src/version.ts (they are
# separate constants; the npm job refuses a tag that disagrees with
# package.json).
# 2. Run manually (workflow_dispatch) → download + inspect the artifacts.
# A manual run never publishes: every publishing job is tag-gated.
# 3. When satisfied, push the version tag:
# git tag v0.7.0 && git push origin v0.7.0
#
# Requires the NPM_TOKEN repository secret (an npm Automation token).

on:
push:
Expand Down Expand Up @@ -208,3 +218,64 @@ jobs:
release/dvalincode-v*-windows-x64.zip
release/dvalincode-v*-evidence.json
release/SHA256SUMS.txt

# npm has drifted from the git tags before: v0.14.1 was tagged and released on
# GitHub but never published to npm, so `npx dvalincode` served a stale build
# until someone noticed. This closes that gap by hand-off, not by discipline.
npm:
name: Publish to npm
needs: [build, attest]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # npm provenance attestation
steps:
# actions/checkout v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
# actions/setup-node v6.4.0
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: 22
cache: npm
registry-url: https://registry.npmjs.org

# A tag that disagrees with package.json would publish a version nobody
# can trace back to a release. Fail loudly instead.
- name: Check the tag matches package.json
id: version
run: |
tag="${GITHUB_REF_NAME#v}"
pkg="$(node -p "require('./package.json').version")"
if [ "$tag" != "$pkg" ]; then
echo "::error::Tag ${GITHUB_REF_NAME} does not match package.json ${pkg}."
exit 1
fi
echo "version=${pkg}" >> "$GITHUB_OUTPUT"

# Re-running a release (a moved tag, a retried job) must not turn into a
# red build just because the version is already on the registry.
- name: Skip when the version is already published
id: published
run: |
if npm view "dvalincode@${{ steps.version.outputs.version }}" version >/dev/null 2>&1; then
echo "already=true" >> "$GITHUB_OUTPUT"
echo "::notice::dvalincode@${{ steps.version.outputs.version }} is already on npm — skipping publish."
else
echo "already=false" >> "$GITHUB_OUTPUT"
fi

- name: Install dependencies
if: steps.published.outputs.already == 'false'
run: npm ci

# `prepublishOnly` re-runs the build and the full check before anything
# leaves the runner. --provenance ties the published tarball to this
# workflow run, the same guarantee the release archives get from attest.
- name: Publish
if: steps.published.outputs.already == 'false'
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}