Skip to content

fix: add retry logic for npm publish transient 404s #68

fix: add retry logic for npm publish transient 404s

fix: add retry logic for npm publish transient 404s #68

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
concurrency:
group: release
cancel-in-progress: false
env:
GH_REPO: AltimateAI/altimate-code
jobs:
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2
with:
bun-version: "1.3.10"
- name: Cache Bun dependencies
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Configure git for tests
run: |
git config --global user.name "CI"
git config --global user.email "ci@test.local"
- name: Install dependencies
run: bun install
- name: Typecheck
run: bun turbo typecheck
- name: Run release-critical tests
run: bun test --timeout 30000 test/branding/ test/install/
working-directory: packages/opencode
build:
name: Build (${{ matrix.name }})
# Runs in PARALLEL with test — publish waits for both
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
# Each target builds ONE binary in parallel (~5 min each)
# Index matches allTargets array in build.ts
- { index: 0, name: "linux-arm64" }
- { index: 1, name: "linux-x64" }
- { index: 2, name: "linux-x64-baseline" }
- { index: 3, name: "linux-arm64-musl" }
- { index: 4, name: "linux-x64-musl" }
- { index: 5, name: "linux-x64-baseline-musl" }
- { index: 6, name: "darwin-arm64" }
- { index: 7, name: "darwin-x64" }
- { index: 8, name: "darwin-x64-baseline" }
- { index: 9, name: "win32-arm64" }
- { index: 10, name: "win32-x64" }
- { index: 11, name: "win32-x64-baseline" }
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2
with:
bun-version: "1.3.10"
- name: Cache Bun dependencies
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install
- name: Build ${{ matrix.name }}
run: bun run packages/opencode/script/build.ts --target-index=${{ matrix.index }}
env:
OPENCODE_VERSION: ${{ github.ref_name }}
OPENCODE_CHANNEL: latest
OPENCODE_RELEASE: "1"
GH_REPO: ${{ env.GH_REPO }}
MODELS_DEV_API_JSON: test/tool/fixtures/models-api.json
# Smoke-test: verify the compiled binary actually starts.
# Only possible for native linux-x64 builds on the ubuntu runner.
# This catches missing externals (e.g. @altimateai/altimate-core)
# that compile fine but crash at runtime.
- name: Smoke test binary
if: matrix.name == 'linux-x64'
run: |
BINARY=$(find packages/opencode/dist -name altimate -type f | head -1)
if [ -z "$BINARY" ]; then
echo "::error::No binary found in dist/"
exit 1
fi
chmod +x "$BINARY"
# Set NODE_PATH so the binary can resolve external NAPI modules
# (mirrors what the npm bin wrapper does at runtime)
NODE_PATH="$(pwd)/packages/opencode/node_modules:$(pwd)/node_modules" "$BINARY" --version
echo "Smoke test passed: binary starts and prints version"
- name: Upload build artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: dist-${{ matrix.name }}
path: packages/opencode/dist/
compression-level: 1
publish-npm:
name: Publish to npm
needs: build
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: read
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2
with:
bun-version: "1.3.10"
- name: Cache Bun dependencies
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: |
bun-${{ runner.os }}-
- name: Install dependencies
run: bun install
- name: Build dbt-tools (bundled with CLI)
run: bun run build
working-directory: packages/dbt-tools
- name: Free disk space for artifact download + npm publish
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /usr/local/share/boost
df -h /
- name: Download all build artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: "dist-*"
path: packages/opencode/dist/
merge-multiple: true
- name: Configure npm auth
run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > "$RUNNER_TEMP/.npmrc"
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# TODO: Uncomment when AUR publishing is enabled (see publish.ts for setup steps)
# - name: Configure SSH for AUR
# if: ${{ !contains(github.ref_name, '-') }}
# run: |
# mkdir -p ~/.ssh
# echo "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/aur
# chmod 600 ~/.ssh/aur
# ssh-keyscan -t ed25519 aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null
# cat >> ~/.ssh/config << 'EOF'
# Host aur.archlinux.org
# IdentityFile ~/.ssh/aur
# User aur
# EOF
# env:
# AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
# Smoke-test a linux-x64 binary from the downloaded artifacts before publishing.
# This is the last gate before npm publish — catches runtime crashes that
# compile-time checks miss (e.g. missing NAPI externals like v0.5.10).
- name: Pre-publish smoke test
run: |
BINARY=$(find packages/opencode/dist -path '*altimate-code-linux-x64/bin/altimate' -type f | head -1)
if [ -z "$BINARY" ]; then
echo "::error::No linux-x64 binary found in artifacts — cannot verify release"
exit 1
else
chmod +x "$BINARY"
NODE_PATH="$(pwd)/packages/opencode/node_modules:$(pwd)/node_modules" "$BINARY" --version
echo "Pre-publish smoke test passed"
fi
- name: Publish to npm
run: bun run packages/opencode/script/publish.ts
env:
OPENCODE_VERSION: ${{ github.ref_name }}
OPENCODE_CHANNEL: latest
OPENCODE_RELEASE: "1"
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_USERCONFIG: ${{ runner.temp }}/.npmrc
GH_REPO: ${{ env.GH_REPO }}
GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
# Python engine (publish-engine) job removed — engine eliminated.
# All methods now run natively in TypeScript.
github-release:
name: Create GitHub Release
needs: [build, publish-npm]
runs-on: ubuntu-latest
timeout-minutes: 60
permissions:
contents: write
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- name: Generate release notes
id: notes
run: |
# Validate tag format to prevent injection
if ! echo "$CURRENT_TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9._-]+)?$'; then
echo "::error::Invalid tag format: $CURRENT_TAG"
exit 1
fi
# Get the previous tag
PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]' | head -2 | tail -1)
# Generate changelog from commits between tags
echo "## What's Changed" > notes.md
echo "" >> notes.md
if [ -n "$PREV_TAG" ]; then
# Categorize commits
echo "### Features" >> notes.md
git log "${PREV_TAG}".."${CURRENT_TAG}" --pretty=format:"- %s (%h)" --grep="^feat" >> notes.md || true
echo "" >> notes.md
echo "" >> notes.md
echo "### Bug Fixes" >> notes.md
git log "${PREV_TAG}".."${CURRENT_TAG}" --pretty=format:"- %s (%h)" --grep="^fix" >> notes.md || true
echo "" >> notes.md
echo "" >> notes.md
echo "### Other Changes" >> notes.md
git log "${PREV_TAG}".."${CURRENT_TAG}" --pretty=format:"- %s (%h)" --invert-grep --grep="^feat" --grep="^fix" >> notes.md || true
echo "" >> notes.md
else
echo "Initial release" >> notes.md
fi
echo "" >> notes.md
echo "### Install" >> notes.md
echo '```bash' >> notes.md
echo "npm install -g @altimateai/altimate-code@${CURRENT_TAG#v}" >> notes.md
echo "# or" >> notes.md
echo "brew install AltimateAI/tap/altimate-code" >> notes.md
echo '```' >> notes.md
echo "" >> notes.md
echo "**Full Changelog**: https://github.com/${GH_REPO}/compare/${PREV_TAG}...${CURRENT_TAG}" >> notes.md
env:
GH_REPO: ${{ env.GH_REPO }}
CURRENT_TAG: ${{ github.ref_name }}
- name: Download all build artifacts
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: "dist-*"
path: packages/opencode/dist/
merge-multiple: true
- name: Create GitHub Release
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
with:
body_path: notes.md
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
files: |
packages/opencode/dist/*.tar.gz
packages/opencode/dist/*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}