refactor(publish): parallel platform jobs with fresh OIDC tokens per job

- Split monolithic publish into build + parallel publish-platform + publish-main + release jobs
- Each platform package gets its own OIDC token (fixes token expiration during large binary uploads)
- Add --prepare-only flag to publish.ts for build step version sync
- Matrix strategy: 7 parallel platform jobs
- publish-main waits for all platforms before publishing main package
This commit is contained in:
justsisyphus
2026-01-22 10:58:35 +09:00
parent 85b7e9737c
commit 8b820c5374
4 changed files with 1053 additions and 54 deletions

View File

@@ -69,10 +69,14 @@ jobs:
- name: Type check
run: bun run typecheck
publish:
# Build everything and upload artifacts
build:
runs-on: ubuntu-latest
needs: [test, typecheck]
if: github.repository == 'code-yeongyu/oh-my-opencode'
outputs:
version: ${{ steps.version.outputs.version }}
dist_tag: ${{ steps.version.outputs.dist_tag }}
steps:
- uses: actions/checkout@v4
with:
@@ -84,78 +88,221 @@ jobs:
with:
bun-version: latest
- uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Upgrade npm for OIDC trusted publishing
run: npm install -g npm@latest
- name: Configure npm registry
run: npm config set registry https://registry.npmjs.org
- name: Install dependencies
run: bun install
env:
BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"
- name: Debug environment
- name: Calculate version
id: version
run: |
echo "=== Bun version ==="
bun --version
echo "=== Node version ==="
node --version
echo "=== Current directory ==="
pwd
echo "=== List src/ ==="
ls -la src/
echo "=== package.json scripts ==="
cat package.json | jq '.scripts'
VERSION="${{ inputs.version }}"
if [ -z "$VERSION" ]; then
PREV=$(curl -s https://registry.npmjs.org/oh-my-opencode/latest | jq -r '.version // "0.0.0"')
BASE="${PREV%%-*}"
IFS='.' read -r MAJOR MINOR PATCH <<< "$BASE"
case "${{ inputs.bump }}" in
major) VERSION="$((MAJOR+1)).0.0" ;;
minor) VERSION="${MAJOR}.$((MINOR+1)).0" ;;
*) VERSION="${MAJOR}.${MINOR}.$((PATCH+1))" ;;
esac
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
# Calculate dist tag
if [[ "$VERSION" == *"-"* ]]; then
DIST_TAG=$(echo "$VERSION" | cut -d'-' -f2 | cut -d'.' -f1)
echo "dist_tag=${DIST_TAG:-next}" >> $GITHUB_OUTPUT
else
echo "dist_tag=" >> $GITHUB_OUTPUT
fi
echo "Version: $VERSION"
- name: Build
- name: Update versions in package.json files
run: bun run script/publish.ts --prepare-only
env:
VERSION: ${{ steps.version.outputs.version }}
- name: Build main package
run: |
echo "=== Running bun build (main) ==="
bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi
echo "=== Running bun build (CLI) ==="
bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi
echo "=== Running tsc ==="
bunx tsc --emitDeclarationOnly
echo "=== Running build:schema ==="
bun run build:schema
- name: Build platform binaries
if: inputs.skip_platform != true
run: bun run build:binaries
- name: Verify build output
run: |
echo "=== dist/ contents ==="
ls -la dist/
echo "=== dist/cli/ contents ==="
ls -la dist/cli/
test -f dist/index.js || (echo "ERROR: dist/index.js not found!" && exit 1)
test -f dist/cli/index.js || (echo "ERROR: dist/cli/index.js not found!" && exit 1)
echo "=== Platform binaries ==="
for platform in darwin-arm64 darwin-x64 linux-x64 linux-arm64 linux-x64-musl linux-arm64-musl; do
test -f "packages/${platform}/bin/oh-my-opencode" || (echo "ERROR: packages/${platform}/bin/oh-my-opencode not found!" && exit 1)
echo "✓ packages/${platform}/bin/oh-my-opencode"
done
test -f "packages/windows-x64/bin/oh-my-opencode.exe" || (echo "ERROR: packages/windows-x64/bin/oh-my-opencode.exe not found!" && exit 1)
echo "✓ packages/windows-x64/bin/oh-my-opencode.exe"
- name: Publish
run: bun run script/publish.ts
- name: Upload main package artifact
uses: actions/upload-artifact@v4
with:
name: main-package
path: |
dist/
package.json
assets/
README.md
LICENSE.md
retention-days: 1
- name: Upload platform artifacts
if: inputs.skip_platform != true
uses: actions/upload-artifact@v4
with:
name: platform-packages
path: packages/
retention-days: 1
- name: Git commit and tag
run: |
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add package.json assets/oh-my-opencode.schema.json packages/*/package.json || true
git diff --cached --quiet || git commit -m "release: v${{ steps.version.outputs.version }}"
git tag -f "v${{ steps.version.outputs.version }}"
git push origin --tags
git push origin HEAD || echo "Branch push failed (non-critical)"
env:
BUMP: ${{ inputs.bump }}
VERSION: ${{ inputs.version }}
SKIP_PLATFORM_PACKAGES: ${{ inputs.skip_platform }}
REPUBLISH: ${{ inputs.republish }}
CI: true
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Publish platform packages in parallel (each job gets fresh OIDC token)
publish-platform:
runs-on: ubuntu-latest
needs: build
if: inputs.skip_platform != true
strategy:
fail-fast: false
matrix:
platform: [darwin-arm64, darwin-x64, linux-x64, linux-arm64, linux-x64-musl, linux-arm64-musl, windows-x64]
steps:
- uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Download platform artifacts
uses: actions/download-artifact@v4
with:
name: platform-packages
path: packages/
- name: Check if already published
id: check
run: |
PKG_NAME="oh-my-opencode-${{ matrix.platform }}"
VERSION="${{ needs.build.outputs.version }}"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/${PKG_NAME}/${VERSION}")
if [ "$STATUS" = "200" ]; then
echo "skip=true" >> $GITHUB_OUTPUT
echo "✓ ${PKG_NAME}@${VERSION} already published"
else
echo "skip=false" >> $GITHUB_OUTPUT
echo "→ ${PKG_NAME}@${VERSION} needs publishing"
fi
- name: Publish ${{ matrix.platform }}
if: steps.check.outputs.skip != 'true'
run: |
cd packages/${{ matrix.platform }}
TAG_ARG=""
if [ -n "${{ needs.build.outputs.dist_tag }}" ]; then
TAG_ARG="--tag ${{ needs.build.outputs.dist_tag }}"
fi
npm publish --access public $TAG_ARG
env:
NPM_CONFIG_PROVENANCE: false
# Publish main package after all platform packages
publish-main:
runs-on: ubuntu-latest
needs: [build, publish-platform]
if: always() && needs.build.result == 'success' && (inputs.skip_platform == true || needs.publish-platform.result == 'success' || needs.publish-platform.result == 'skipped')
steps:
- uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Download main package artifact
uses: actions/download-artifact@v4
with:
name: main-package
path: .
- name: Check if already published
id: check
run: |
VERSION="${{ needs.build.outputs.version }}"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode/${VERSION}")
if [ "$STATUS" = "200" ]; then
echo "skip=true" >> $GITHUB_OUTPUT
echo "✓ oh-my-opencode@${VERSION} already published"
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: Publish main package
if: steps.check.outputs.skip != 'true'
run: |
TAG_ARG=""
if [ -n "${{ needs.build.outputs.dist_tag }}" ]; then
TAG_ARG="--tag ${{ needs.build.outputs.dist_tag }}"
fi
npm publish --access public --provenance $TAG_ARG
env:
NPM_CONFIG_PROVENANCE: true
# Create release and cleanup
release:
runs-on: ubuntu-latest
needs: [build, publish-main]
if: always() && needs.build.result == 'success'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
run: |
VERSION="${{ needs.build.outputs.version }}"
# Find previous tag
PREV_TAG=""
if [[ "$VERSION" == *"-beta."* ]]; then
BASE="${VERSION%-beta.*}"
NUM="${VERSION##*-beta.}"
PREV_NUM=$((NUM - 1))
if [ $PREV_NUM -ge 1 ]; then
PREV_TAG="${BASE}-beta.${PREV_NUM}"
git rev-parse "v${PREV_TAG}" >/dev/null 2>&1 || PREV_TAG=""
fi
fi
if [ -z "$PREV_TAG" ]; then
PREV_TAG=$(curl -s https://registry.npmjs.org/oh-my-opencode/latest | jq -r '.version // "0.0.0"')
fi
echo "Comparing v${PREV_TAG}..v${VERSION}"
NOTES=$(git log "v${PREV_TAG}..v${VERSION}" --oneline --format="- %h %s" 2>/dev/null | grep -vE "^- \w+ (ignore:|test:|chore:|ci:|release:)" || echo "No notable changes")
# Write to file for multiline support
echo "$NOTES" > /tmp/changelog.md
echo "notes_file=/tmp/changelog.md" >> $GITHUB_OUTPUT
- name: Create GitHub release
run: |
VERSION="${{ needs.build.outputs.version }}"
gh release view "v${VERSION}" >/dev/null 2>&1 || \
gh release create "v${VERSION}" --title "v${VERSION}" --notes-file /tmp/changelog.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Delete draft release
run: gh release delete next --yes 2>/dev/null || echo "No draft release to delete"
run: gh release delete next --yes 2>/dev/null || true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -164,8 +311,10 @@ jobs:
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
VERSION=$(jq -r '.version' package.json)
VERSION="${{ needs.build.outputs.version }}"
git stash --include-untracked || true
git checkout master
git reset --hard "v${VERSION}"
git push -f origin master || echo "::warning::Failed to push to master. This can happen when workflow files changed. Manually sync master: git checkout master && git reset --hard v${VERSION} && git push -f"
git push -f origin master || echo "::warning::Failed to push to master"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}