Skip to content

Merge pull request #48 from quantfive/github-in-js #194

Merge pull request #48 from quantfive/github-in-js

Merge pull request #48 from quantfive/github-in-js #194

Workflow file for this run

name: Release and Publish
on:
push:
branches: ["**"]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
NODE_VERSION: "20"
REGISTRY_URL: "https://registry.npmjs.org"
SCOPE: "@codepress"
jobs:
check-version:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
outputs:
version_changed: ${{ steps.release_info.outputs.changed }}
release_version: ${{ steps.release_info.outputs.release_version }}
release_tag: ${{ steps.release_info.outputs.release_tag }}
branch_name: ${{ steps.release_info.outputs.branch_name }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
# Configure npmjs.org as registry (scoped for @codepress)
- name: Setup Node (scoped registry)
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: ${{ env.REGISTRY_URL }}
scope: ${{ env.SCOPE }}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.22.0
- name: Install dependencies
run: pnpm install --frozen-lockfile
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Compute release metadata
id: release_info
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
CURRENT_VERSION=$(node -p "require('./package.json').version")
BRANCH_NAME=${GITHUB_REF#refs/heads/}
TIMESTAMP=$(date +%Y%m%d%H%M%S)
if [[ "$BRANCH_NAME" == "main" ]]; then
RELEASE_VERSION="$CURRENT_VERSION"
RELEASE_TAG="latest"
elif [[ "$BRANCH_NAME" == "develop" ]]; then
RELEASE_VERSION="$CURRENT_VERSION-beta.$TIMESTAMP"
RELEASE_TAG="beta"
elif [[ "$BRANCH_NAME" =~ ^feature/ ]]; then
FEATURE_NAME=$(echo "$BRANCH_NAME" | sed 's/feature\///' | sed 's/[^a-zA-Z0-9]/-/g')
RELEASE_VERSION="$CURRENT_VERSION-alpha.$FEATURE_NAME.$TIMESTAMP"
RELEASE_TAG="alpha"
else
SAFE_BRANCH=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9]/-/g')
RELEASE_VERSION="$CURRENT_VERSION-dev.$SAFE_BRANCH.$TIMESTAMP"
RELEASE_TAG="dev"
fi
echo "release_version=$RELEASE_VERSION" >> $GITHUB_OUTPUT
echo "release_tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
if git tag | grep -q "^v$RELEASE_VERSION$"; then
echo "Version v$RELEASE_VERSION already tagged"
echo "changed=false" >> $GITHUB_OUTPUT
exit 0
fi
if [[ "$BRANCH_NAME" == "main" ]]; then
LATEST_PUBLISHED=$(npm view @codepress/codepress-engine version 2>/dev/null || echo "0.0.0")
if [ "$RELEASE_VERSION" != "$LATEST_PUBLISHED" ]; then
echo "changed=true" >> $GITHUB_OUTPUT
else
echo "changed=false" >> $GITHUB_OUTPUT
fi
else
echo "changed=true" >> $GITHUB_OUTPUT
fi
# Build each WASM band in parallel using matrix strategy
build-wasm:
needs: check-version
if: needs.check-version.outputs.version_changed == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
band: [v0_82_87, v26, v42, v48]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.22.0
- name: Setup Rust (stable + WASI)
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1
- name: Cache Cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-${{ matrix.band }}-${{ hashFiles('codepress-swc-plugin/src/**', 'scripts/build-swc.mjs') }}
restore-keys: |
${{ runner.os }}-cargo-${{ matrix.band }}-
${{ runner.os }}-cargo-
- name: Install deps
run: pnpm install --frozen-lockfile
- name: Build WASM band ${{ matrix.band }}
run: node scripts/build-swc.mjs
env:
BAND: ${{ matrix.band }}
- name: Verify WASM build
run: |
echo "Built WASM files:"
ls -la swc/*.wasm
for f in swc/*.wasm; do
echo "MD5 of $f:"
md5sum "$f" || md5 "$f"
done
- name: Upload WASM artifact
uses: actions/upload-artifact@v4
with:
name: wasm-${{ matrix.band }}
path: swc/*.wasm
retention-days: 1
build-and-publish:
needs: [check-version, build-wasm]
if: needs.check-version.outputs.version_changed == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node (scoped registry)
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: ${{ env.REGISTRY_URL }}
scope: ${{ env.SCOPE }}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10.22.0
- name: Install deps
run: pnpm install --frozen-lockfile
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Download all WASM artifacts
uses: actions/download-artifact@v4
with:
pattern: wasm-*
path: swc-artifacts
merge-multiple: false
- name: Combine WASM artifacts
run: |
mkdir -p swc
for dir in swc-artifacts/wasm-*; do
cp "$dir"/*.wasm swc/ 2>/dev/null || true
done
ls -la swc/
- name: Verify all WASM files present
run: |
echo "Verifying WASM artifacts for all bands..."
MISSING_BANDS=""
BANDS=("v0_82_87" "v26" "v42" "v48")
for band in "${BANDS[@]}"; do
if ! ls swc/*${band}*.wasm 1>/dev/null 2>&1; then
echo "ERROR: Missing WASM file for band: $band"
MISSING_BANDS="$MISSING_BANDS $band"
else
echo "✓ Found WASM file(s) for band: $band"
ls swc/*${band}*.wasm
fi
done
if [ -n "$MISSING_BANDS" ]; then
echo ""
echo "FATAL: The following bands are missing WASM artifacts:$MISSING_BANDS"
echo "This indicates one or more matrix build jobs failed."
echo "Cannot proceed with publish - package would be incomplete."
exit 1
fi
echo ""
echo "✓ All WASM bands verified successfully"
echo "Total WASM files: $(ls swc/*.wasm | wc -l)"
- name: Update package version for release
env:
RELEASE_VERSION: ${{ needs.check-version.outputs.release_version }}
run: |
node -e "
const fs = require('fs');
const version = process.env.RELEASE_VERSION;
const pkgPath = './package.json';
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
pkg.version = version;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
"
- name: Build JS
run: pnpm run build
- name: Run tests
run: pnpm test
# Optional: verify the pack contents before publishing
- name: Dry-run pack
run: npm pack --dry-run --ignore-scripts
# Race safety: re-check just before publish
- name: Ensure version not yet published
id: recheck
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
TARGET_VERSION: ${{ needs.check-version.outputs.release_version }}
run: |
PUBLISHED=$(npm view @codepress/codepress-engine versions --json 2>/dev/null || echo '[]')
if printf '%s' "$PUBLISHED" | grep -F "\"$TARGET_VERSION\"" >/dev/null; then
echo "already=true" >> $GITHUB_OUTPUT
else
echo "already=false" >> $GITHUB_OUTPUT
fi
- name: Publish to npm
if: steps.recheck.outputs.already == 'false'
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
RELEASE_TAG: ${{ needs.check-version.outputs.release_tag }}
run: |
if [ "$RELEASE_TAG" = "latest" ]; then
npm publish --ignore-scripts
else
npm publish --ignore-scripts --tag "$RELEASE_TAG"
fi
- name: Create Git tag (after successful publish)
if: steps.recheck.outputs.already == 'false'
run: |
VERSION=${{ needs.check-version.outputs.release_version }}
BRANCH_NAME=${{ needs.check-version.outputs.branch_name }}
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git tag -a "v$VERSION" -m "Release v$VERSION from $BRANCH_NAME"
git push origin "v$VERSION"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.check-version.outputs.release_version }}
name: Engine v${{ needs.check-version.outputs.release_version }}
prerelease: ${{ needs.check-version.outputs.release_tag != 'latest' }}
generate_release_notes: true
body: |
## CodePress Engine Release
**Branch**: `${{ needs.check-version.outputs.branch_name }}`
**Dist Tag**: `${{ needs.check-version.outputs.release_tag }}`
```bash
# Install the published dist-tag from npm (defaults to latest on main)
npm install @codepress/codepress-engine@${{ needs.check-version.outputs.release_tag }}
# Pin to this exact release version from npm
npm install @codepress/codepress-engine@${{ needs.check-version.outputs.release_version }}
```
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}