Skip to content

Commit 7d63647

Browse files
committed
refactor: use reusable workflow instead of composite action
- Convert publish.yml to reusable workflow with workflow_call trigger - Move npm publish logic directly into publish.yml (no composite action) - Update ci.yml to call publish.yml instead of using composite action - Simplifies OIDC authentication by keeping publish in workflow context - publish.yml now triggers on both tag pushes and workflow_call from ci.yml
1 parent e42ea6b commit 7d63647

2 files changed

Lines changed: 110 additions & 23 deletions

File tree

.github/workflows/ci.yml

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -114,31 +114,13 @@ jobs:
114114
- name: Build library
115115
run: bun run build
116116

117+
# Call publish workflow after all checks pass on main
117118
publish:
118119
name: publish to npm
119-
runs-on: ubuntu-latest
120120
# Only publish on main branch pushes after all checks pass
121121
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
122122
needs: [fmt, lint, typecheck, test, build]
123+
uses: ./.github/workflows/publish.yml
123124
permissions:
124125
contents: read
125126
id-token: write # Required for OIDC trusted publishing
126-
steps:
127-
- name: Checkout code
128-
uses: actions/checkout@v4
129-
with:
130-
fetch-depth: 0 # Required for git describe to find tags
131-
132-
- uses: oven-sh/setup-bun@v1
133-
with:
134-
bun-version: latest
135-
136-
- name: Install dependencies
137-
run: bun install
138-
139-
- uses: ./.github/actions/setup-zig
140-
with:
141-
version: 0.15.2
142-
143-
- name: Publish to NPM
144-
uses: ./.github/actions/npm-publish

.github/workflows/publish.yml

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ on:
44
push:
55
tags:
66
- 'v*'
7+
workflow_call:
8+
# Allow calling from other workflows (e.g., ci.yml)
79

810
permissions:
911
contents: read
@@ -14,7 +16,7 @@ jobs:
1416
name: publish to npm
1517
runs-on: ubuntu-latest
1618
steps:
17-
- name: Checkout tag
19+
- name: Checkout code
1820
uses: actions/checkout@v4
1921
with:
2022
ref: ${{ github.ref }}
@@ -52,5 +54,108 @@ jobs:
5254
- name: Build library
5355
run: bun run build
5456

55-
- name: Publish to NPM
56-
uses: ./.github/actions/npm-publish
57+
- name: Setup Node.js for npm
58+
uses: actions/setup-node@v4
59+
with:
60+
node-version: '20'
61+
registry-url: 'https://registry.npmjs.org'
62+
63+
- name: Detect trigger type
64+
id: detect
65+
run: |
66+
if [[ $GITHUB_REF == refs/tags/* ]]; then
67+
echo "is_tag=true" >> $GITHUB_OUTPUT
68+
echo "trigger_type=tag" >> $GITHUB_OUTPUT
69+
echo "trigger_name=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
70+
echo "📦 Detected tag push: ${GITHUB_REF#refs/tags/}"
71+
else
72+
echo "is_tag=false" >> $GITHUB_OUTPUT
73+
echo "trigger_type=branch" >> $GITHUB_OUTPUT
74+
echo "trigger_name=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
75+
echo "🚧 Detected branch push: ${GITHUB_REF#refs/heads/}"
76+
fi
77+
78+
- name: Generate version
79+
id: version
80+
run: |
81+
# Get base version from package.json
82+
BASE_VERSION=$(jq -r .version package.json)
83+
84+
if [[ "${{ steps.detect.outputs.is_tag }}" == "true" ]]; then
85+
# For tags, use the base version as-is (stable release)
86+
NPM_VERSION="${BASE_VERSION}"
87+
NPM_TAG="latest"
88+
echo "📦 Publishing stable release: ${NPM_VERSION}"
89+
else
90+
# For main branch, create a pre-release version using git describe
91+
# Format: 0.3.0-next.5.g1a2b3c4 (base-next.commits.hash)
92+
GIT_COMMIT=$(git rev-parse --short HEAD)
93+
COMMITS_SINCE_TAG=$(git rev-list --count HEAD ^$(git describe --tags --abbrev=0 2>/dev/null || echo HEAD) 2>/dev/null || echo "0")
94+
NPM_VERSION="${BASE_VERSION}-next.${COMMITS_SINCE_TAG}.g${GIT_COMMIT}"
95+
NPM_TAG="next"
96+
echo "🚧 Publishing pre-release: ${NPM_VERSION}"
97+
fi
98+
99+
echo "version=${NPM_VERSION}" >> $GITHUB_OUTPUT
100+
echo "tag=${NPM_TAG}" >> $GITHUB_OUTPUT
101+
102+
# Update package.json with the new version
103+
node -e "const fs = require('fs'); const pkg = JSON.parse(fs.readFileSync('package.json')); pkg.version = '${NPM_VERSION}'; fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');"
104+
105+
echo "Updated package.json to version ${NPM_VERSION}"
106+
107+
- name: Validate tag matches package.json version
108+
if: steps.detect.outputs.is_tag == 'true'
109+
run: |
110+
# Extract version from package.json
111+
PKG_VERSION=$(jq -r .version package.json)
112+
113+
# Extract version from git tag (strip 'v' prefix)
114+
TAG_VERSION=${GITHUB_REF#refs/tags/v}
115+
116+
echo "Package version: $PKG_VERSION"
117+
echo "Tag version: $TAG_VERSION"
118+
119+
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
120+
echo "❌ Error: Version mismatch!"
121+
echo " package.json version: $PKG_VERSION"
122+
echo " Git tag version: $TAG_VERSION"
123+
echo ""
124+
echo "Please ensure the git tag matches the version in package.json"
125+
exit 1
126+
fi
127+
128+
echo "✅ Version validation passed: $PKG_VERSION"
129+
130+
- name: Check if version exists
131+
id: check-exists
132+
run: |
133+
PACKAGE_NAME=$(node -p "require('./package.json').name")
134+
VERSION="${{ steps.version.outputs.version }}"
135+
136+
if npm view "${PACKAGE_NAME}@${VERSION}" version &>/dev/null; then
137+
echo "exists=true" >> $GITHUB_OUTPUT
138+
echo "Version ${VERSION} already exists on npm"
139+
else
140+
echo "exists=false" >> $GITHUB_OUTPUT
141+
echo "Version ${VERSION} does not exist, will publish"
142+
fi
143+
144+
- name: Publish to npm (with OIDC trusted publishing)
145+
if: steps.check-exists.outputs.exists == 'false'
146+
run: npm publish --tag ${{ steps.version.outputs.tag }} --provenance --access public
147+
148+
- name: Update dist-tag (version already exists)
149+
if: steps.check-exists.outputs.exists == 'true' && steps.detect.outputs.is_tag == 'true'
150+
run: |
151+
PACKAGE_NAME=$(node -p "require('./package.json').name")
152+
VERSION="${{ steps.version.outputs.version }}"
153+
TAG="${{ steps.version.outputs.tag }}"
154+
155+
echo "Version ${VERSION} already published, updating dist-tag to ${TAG}"
156+
npm dist-tag add "${PACKAGE_NAME}@${VERSION}" "${TAG}"
157+
158+
- name: Skip (pre-release already exists)
159+
if: steps.check-exists.outputs.exists == 'true' && steps.detect.outputs.is_tag != 'true'
160+
run: |
161+
echo "⏭️ Pre-release version already exists, skipping"

0 commit comments

Comments
 (0)