Skip to content

Commit bf1a16b

Browse files
feat: consolidate dev + stable publish into single workflow
Merge dev-publish and stable-publish into one publish.yml to satisfy npm Trusted Publishing's one-workflow-per-package constraint. - push to main → dev release (e.g. 2.0.1-dev.abc1234) with --tag dev - GitHub Release event → stable release with --tag latest - Concurrency group cancels in-flight dev publishes on rapid merges - Skip logic for stable version bump commits (chore: release v*) - Version computed in dedicated job, shared via outputs - No git commits/tags/PRs for dev releases
1 parent e8ac4fa commit bf1a16b

2 files changed

Lines changed: 95 additions & 32 deletions

File tree

.github/workflows/dev-publish.yml

Whitespace-only changes.

.github/workflows/publish.yml

Lines changed: 95 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
name: Publish
22

33
on:
4+
push:
5+
branches: [main]
46
release:
57
types: [published]
68

9+
concurrency:
10+
group: publish
11+
cancel-in-progress: true
12+
713
permissions: {}
814

915
jobs:
1016
preflight:
1117
name: Preflight checks
1218
runs-on: ubuntu-latest
19+
# Skip dev publish when the push is a stable release version bump
20+
if: github.event_name == 'release' || !startsWith(github.event.head_commit.message, 'chore: release v')
1321
permissions:
1422
contents: read
1523
steps:
@@ -20,6 +28,39 @@ jobs:
2028
- run: npm install
2129
- run: npm test
2230

31+
compute-version:
32+
needs: preflight
33+
runs-on: ubuntu-latest
34+
permissions:
35+
contents: read
36+
outputs:
37+
version: ${{ steps.compute.outputs.version }}
38+
npm_tag: ${{ steps.compute.outputs.npm_tag }}
39+
steps:
40+
- uses: actions/checkout@v4
41+
42+
- name: Compute version
43+
id: compute
44+
run: |
45+
CURRENT=$(node -p "require('./package.json').version")
46+
47+
if [ "${{ github.event_name }}" = "release" ]; then
48+
TAG="${{ github.event.release.tag_name }}"
49+
VERSION="${TAG#v}"
50+
NPM_TAG="latest"
51+
echo "Stable release: $VERSION (from tag $TAG)"
52+
else
53+
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
54+
NEXT_PATCH=$((PATCH + 1))
55+
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
56+
VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}-dev.${SHORT_SHA}"
57+
NPM_TAG="dev"
58+
echo "Dev release: $VERSION"
59+
fi
60+
61+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
62+
echo "npm_tag=$NPM_TAG" >> "$GITHUB_OUTPUT"
63+
2364
build-native:
2465
needs: preflight
2566
strategy:
@@ -81,7 +122,7 @@ jobs:
81122
if-no-files-found: error
82123

83124
publish:
84-
needs: build-native
125+
needs: [compute-version, build-native]
85126
runs-on: ubuntu-latest
86127
environment: npm-publish
87128
permissions:
@@ -106,52 +147,42 @@ jobs:
106147

107148
- run: npm install
108149

109-
- name: Configure git
110-
run: |
111-
git config user.name "github-actions[bot]"
112-
git config user.email "github-actions[bot]@users.noreply.github.com"
113-
114-
- name: Bump version
150+
- name: Set version
115151
id: version
152+
env:
153+
VERSION: ${{ needs.compute-version.outputs.version }}
116154
run: |
117155
git checkout -- package-lock.json
118-
CURRENT=$(node -p "require('./package.json').version")
156+
npm version "$VERSION" --no-git-tag-version
157+
node scripts/sync-native-versions.js
158+
echo "Publishing version $VERSION"
119159
120-
# Extract version from the release tag
121-
TAG="${{ github.event.release.tag_name }}"
122-
RELEASE_VERSION="${TAG#v}"
123-
if [ "$CURRENT" != "$RELEASE_VERSION" ]; then
124-
echo "::warning::package.json ($CURRENT) doesn't match release tag ($TAG) — bumping to match"
125-
npx commit-and-tag-version --release-as "$RELEASE_VERSION" --skip.tag --skip.changelog
126-
else
127-
echo "Version $CURRENT already matches tag $TAG"
128-
fi
129-
130-
NEW_VERSION=$(node -p "require('./package.json').version")
131-
echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
132-
echo "Will publish version $NEW_VERSION"
160+
- name: Disable prepublishOnly
161+
run: npm pkg set scripts.prepublishOnly=""
133162

134163
- name: Download native artifacts
135164
uses: actions/download-artifact@v4
136165
with:
137166
path: artifacts/
138167

139168
- name: Verify version not already on npm
169+
env:
170+
VERSION: ${{ needs.compute-version.outputs.version }}
140171
run: |
141-
VERSION="${{ steps.version.outputs.new_version }}"
142172
PKG="@optave/codegraph"
143173
echo "Checking if $PKG@$VERSION already exists on npm..."
144174
if npm view "$PKG@$VERSION" version 2>/dev/null; then
145-
echo "::error::$PKG@$VERSION is already published on npm. Bump to a higher version."
175+
echo "::error::$PKG@$VERSION is already published on npm."
146176
exit 1
147177
fi
148178
echo "$PKG@$VERSION is not yet published — proceeding"
149179
150180
- name: Publish platform packages
181+
env:
182+
VERSION: ${{ needs.compute-version.outputs.version }}
183+
NPM_TAG: ${{ needs.compute-version.outputs.npm_tag }}
151184
shell: bash
152185
run: |
153-
VERSION="${{ steps.version.outputs.new_version }}"
154-
155186
declare -A PACKAGES=(
156187
["linux-x64"]="@optave/codegraph-linux-x64-gnu"
157188
["darwin-arm64"]="@optave/codegraph-darwin-arm64"
@@ -185,28 +216,38 @@ jobs:
185216
}
186217
PKGJSON
187218
188-
echo "Publishing ${pkg_name}@${VERSION}"
189-
npm publish "./pkg/$platform" --access public --provenance --tag latest
219+
echo "Publishing ${pkg_name}@${VERSION} with --tag ${NPM_TAG}"
220+
npm publish "./pkg/$platform" --access public --provenance --tag "$NPM_TAG"
190221
done
191222
192-
- name: Disable prepublishOnly
193-
run: npm pkg set scripts.prepublishOnly=""
194-
195223
- name: Publish main package
196-
run: npm publish --access public --provenance --tag latest
224+
env:
225+
NPM_TAG: ${{ needs.compute-version.outputs.npm_tag }}
226+
run: npm publish --access public --provenance --tag "$NPM_TAG"
227+
228+
# ── Stable-only: version bump PR and tag ──
229+
230+
- name: Configure git
231+
if: github.event_name == 'release'
232+
run: |
233+
git config user.name "github-actions[bot]"
234+
git config user.email "github-actions[bot]@users.noreply.github.com"
197235
198236
- name: Push version bump via PR
237+
if: github.event_name == 'release'
199238
env:
200239
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
240+
VERSION: ${{ needs.compute-version.outputs.version }}
201241
run: |
202-
VERSION="${{ steps.version.outputs.new_version }}"
203242
TAG="v${VERSION}"
204243
BRANCH="release/v${VERSION}"
205244
206245
# Check if there are version bump changes to push
207246
if git diff --quiet HEAD; then
208247
echo "No version bump commit to push — skipping PR"
209248
else
249+
git add -A
250+
git commit -m "chore: release v${VERSION}"
210251
git push origin "HEAD:refs/heads/${BRANCH}"
211252
gh pr create \
212253
--base main \
@@ -223,3 +264,25 @@ jobs:
223264
git tag -a "$TAG" -m "release: $TAG"
224265
git push origin "$TAG"
225266
fi
267+
268+
# ── Dev-only: summary with install instructions ──
269+
270+
- name: Summary
271+
if: github.event_name == 'push'
272+
env:
273+
VERSION: ${{ needs.compute-version.outputs.version }}
274+
run: |
275+
cat >> "$GITHUB_STEP_SUMMARY" <<EOF
276+
## Dev Release Published
277+
278+
**Version:** \`${VERSION}\`
279+
**Commit:** \`${{ github.sha }}\`
280+
281+
### Install
282+
283+
\`\`\`bash
284+
npm install @optave/codegraph@dev
285+
# or pin this exact version:
286+
npm install @optave/codegraph@${VERSION}
287+
\`\`\`
288+
EOF

0 commit comments

Comments
 (0)