fix: prevent worker from stopping when another session is still active #449
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Release | |
| "on": | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Version to build binaries for (e.g., 3.3.0)" | |
| required: true | |
| type: string | |
| changelog: | |
| description: "Custom changelog content (optional - overrides generated changelog)" | |
| required: false | |
| type: string | |
| jobs: | |
| # Check if this commit should trigger a release | |
| check-trigger: | |
| name: Check Release Trigger | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_run: ${{ steps.check.outputs.should_run }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| fetch-depth: 2 | |
| - name: Check commit message | |
| id: check | |
| run: | | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| echo "Manual trigger - proceeding" | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| COMMIT_MSG=$(git log -1 --pretty=%B) | |
| echo "Commit message: $COMMIT_MSG" | |
| # Check for fix: or feat: prefix (first line or squash merge body) | |
| if echo "$COMMIT_MSG" | grep -qE "(^|\* )(fix|feat):"; then | |
| echo "Release commit detected (fix: or feat:)" | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Check for merge from dev branch | |
| if echo "$COMMIT_MSG" | grep -qE "^Merge (branch 'dev'|pull request .* from .*/dev)"; then | |
| echo "Merge from dev detected" | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| echo "Not a release trigger commit - skipping" | |
| echo "should_run=false" >> "$GITHUB_OUTPUT" | |
| security-scan: | |
| name: Security Scan (Trivy) | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: check-trigger | |
| if: needs.check-trigger.outputs.should_run == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Run Trivy vulnerability and secret scanner | |
| uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| scanners: 'vuln,secret' | |
| severity: 'CRITICAL,HIGH' | |
| exit-code: '1' | |
| ignore-unfixed: true | |
| skip-dirs: '.venv,node_modules,console/node_modules,launcher,docs/site/api' | |
| trivyignores: '.trivyignore' | |
| format: 'table' | |
| output: trivy-results.txt | |
| - name: Publish Trivy results to step summary | |
| if: always() | |
| run: | | |
| if [[ -s trivy-results.txt ]]; then | |
| { | |
| echo "### Security Scan Results" | |
| echo "<details><summary>Click to expand Trivy output</summary>" | |
| echo "" | |
| echo '```' | |
| cat trivy-results.txt | |
| echo '```' | |
| echo "</details>" | |
| } >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "### Security Scan: No issues found" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| python-tests: | |
| name: Python Unit Tests | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: check-trigger | |
| if: needs.check-trigger.outputs.should_run == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install git-crypt | |
| run: sudo apt-get update && sudo apt-get install -y git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install Python dependencies | |
| run: | | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install . pytest pytest-cov pytest-asyncio | |
| - name: Run unit tests with coverage | |
| run: | | |
| python3 -m pytest installer/tests/unit/ launcher/tests/unit/ pilot/hooks/tests/ -v \ | |
| --cov=installer --cov=launcher --cov=pilot.hooks \ | |
| --cov-report=term --cov-report=xml | |
| console-tests: | |
| name: Console Unit Tests | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: check-trigger | |
| if: needs.check-trigger.outputs.should_run == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| working-directory: console | |
| run: bun install | |
| - name: Run console tests | |
| working-directory: console | |
| run: bun test | |
| console-build: | |
| name: Console Build & Typecheck | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: check-trigger | |
| if: needs.check-trigger.outputs.should_run == 'true' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 | |
| with: | |
| node-version: "22" | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| working-directory: console | |
| run: bun install | |
| - name: Typecheck | |
| working-directory: console | |
| run: bun run typecheck | |
| - name: Build hooks | |
| working-directory: console | |
| run: bun run build | |
| - name: Build viewer | |
| working-directory: console | |
| run: bun run build:viewer | |
| # Determine the version to release (semantic-release dry-run or manual input) | |
| prepare-release: | |
| name: Prepare Release | |
| permissions: | |
| contents: write | |
| runs-on: ubuntu-latest | |
| needs: check-trigger | |
| if: needs.check-trigger.outputs.should_run == 'true' | |
| outputs: | |
| should_release: ${{ steps.check.outputs.should_release }} | |
| version: ${{ steps.check.outputs.version }} | |
| current_version: ${{ steps.check.outputs.current_version }} | |
| changelog: ${{ steps.git-cliff.outputs.content }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Install git-crypt | |
| run: sudo apt-get update && sudo apt-get install -y git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 | |
| with: | |
| node-version: "22" | |
| - name: Get current version | |
| id: current | |
| run: | | |
| CURRENT=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo "0.0.0") | |
| echo "Current version: $CURRENT" | |
| echo "version=$CURRENT" >> "$GITHUB_OUTPUT" | |
| - name: Check for release | |
| id: check | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "current_version=${{ steps.current.outputs.version }}" >> "$GITHUB_OUTPUT" | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| echo "Manual trigger with version ${{ inputs.version }}" | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT" | |
| else | |
| # Install semantic-release and plugins | |
| npm install -g semantic-release \ | |
| @semantic-release/git \ | |
| @semantic-release/exec | |
| # Run dry-run to check if release is needed | |
| SR_OUT=/tmp/sr-output.txt | |
| if npx semantic-release --dry-run 2>&1 | tee $SR_OUT \ | |
| | grep -q "Published release"; then | |
| VERSION=$(grep "next release version" $SR_OUT \ | |
| | grep -oP '\d+\.\d+\.\d+' | head -1) | |
| if [ -z "$VERSION" ]; then | |
| VERSION=$(grep -oP 'Published release \K\d+\.\d+\.\d+' \ | |
| $SR_OUT | head -1) | |
| fi | |
| echo "Will release version: $VERSION" | |
| echo "should_release=true" >> "$GITHUB_OUTPUT" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No release needed" | |
| echo "should_release=false" >> "$GITHUB_OUTPUT" | |
| echo "version=" >> "$GITHUB_OUTPUT" | |
| fi | |
| fi | |
| - name: Generate changelog with git-cliff | |
| if: steps.check.outputs.should_release == 'true' | |
| id: git-cliff | |
| uses: orhun/git-cliff-action@e16f179f0be49ecdfe63753837f20b9531642772 # v4 | |
| with: | |
| config: cliff.toml | |
| args: v6.0.0.. --unreleased --tag v${{ steps.check.outputs.version }} | |
| env: | |
| OUTPUT: CHANGES.md | |
| GITHUB_REPO: ${{ github.repository }} | |
| # Build jobs run in parallel after prepare-release | |
| build-pilot-x86: | |
| name: Build Pilot Linux x86_64 | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: prepare-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install git-crypt | |
| run: sudo apt-get update && sudo apt-get install -y git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Verify version | |
| run: | | |
| echo "Building version: ${{ needs.prepare-release.outputs.version }}" | |
| cat launcher/__init__.py | grep __version__ | |
| - name: Build binary | |
| run: | | |
| docker run --rm \ | |
| -v ${{ github.workspace }}:/workspace \ | |
| -w /workspace \ | |
| -e BUILD_VERSION=${{ needs.prepare-release.outputs.version }} \ | |
| python:3.12-slim-bullseye \ | |
| bash -c " | |
| apt-get update && apt-get install -y binutils build-essential && \ | |
| pip install . && \ | |
| python -m launcher.build --release --version \$BUILD_VERSION && \ | |
| ls -la launcher/dist/ | |
| " | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: pilot-linux-x86_64 | |
| path: | | |
| launcher/dist/pilot-linux-x86_64.so | |
| launcher/dist/pilot | |
| retention-days: 1 | |
| build-pilot-arm64: | |
| name: Build Pilot Linux arm64 | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-24.04-arm | |
| needs: prepare-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install git-crypt | |
| run: sudo apt-get update && sudo apt-get install -y git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Verify version | |
| run: | | |
| echo "Building version: ${{ needs.prepare-release.outputs.version }}" | |
| cat launcher/__init__.py | grep __version__ | |
| - name: Build binary | |
| run: | | |
| docker run --rm \ | |
| -v ${{ github.workspace }}:/workspace \ | |
| -w /workspace \ | |
| -e BUILD_VERSION=${{ needs.prepare-release.outputs.version }} \ | |
| python:3.12-slim-bullseye \ | |
| bash -c " | |
| apt-get update && apt-get install -y binutils build-essential && \ | |
| pip install . && \ | |
| python -m launcher.build --release --version \$BUILD_VERSION && \ | |
| ls -la launcher/dist/ | |
| " | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: pilot-linux-arm64 | |
| path: launcher/dist/pilot-linux-arm64.so | |
| retention-days: 1 | |
| build-pilot-darwin-x86: | |
| name: Build Pilot Darwin x86_64 | |
| permissions: | |
| contents: read | |
| runs-on: macos-15-intel | |
| needs: prepare-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install git-crypt | |
| run: brew install git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Cache pip dependencies | |
| uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 | |
| with: | |
| path: ~/Library/Caches/pip | |
| key: ${{ runner.os }}-pip-pyinstaller | |
| restore-keys: ${{ runner.os }}-pip- | |
| - name: Verify version | |
| run: | | |
| echo "Building version: ${{ needs.prepare-release.outputs.version }}" | |
| cat launcher/__init__.py | grep __version__ | |
| - name: Build binary | |
| run: | | |
| pip install . | |
| python -m launcher.build --release --version ${{ needs.prepare-release.outputs.version }} | |
| ls -la launcher/dist/ | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: pilot-darwin-x86_64 | |
| path: launcher/dist/pilot-darwin-x86_64.so | |
| retention-days: 1 | |
| build-pilot-darwin-arm64: | |
| name: Build Pilot Darwin arm64 | |
| permissions: | |
| contents: read | |
| runs-on: macos-14 | |
| needs: prepare-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install git-crypt | |
| run: brew install git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Cache pip dependencies | |
| uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5 | |
| with: | |
| path: ~/Library/Caches/pip | |
| key: ${{ runner.os }}-pip-pyinstaller | |
| restore-keys: ${{ runner.os }}-pip- | |
| - name: Verify version | |
| run: | | |
| echo "Building version: ${{ needs.prepare-release.outputs.version }}" | |
| cat launcher/__init__.py | grep __version__ | |
| - name: Build binary | |
| run: | | |
| pip install . | |
| python -m launcher.build --release --version ${{ needs.prepare-release.outputs.version }} | |
| ls -la launcher/dist/ | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: pilot-darwin-arm64 | |
| path: launcher/dist/pilot-darwin-arm64.so | |
| retention-days: 1 | |
| # Manual approval gate - displays version and changelog, waits for approval | |
| approve-release: | |
| name: Approve Release | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: | |
| - prepare-release | |
| - python-tests | |
| - console-tests | |
| - console-build | |
| - build-pilot-x86 | |
| - build-pilot-arm64 | |
| - build-pilot-darwin-x86 | |
| - build-pilot-darwin-arm64 | |
| - security-scan | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| environment: production | |
| steps: | |
| - name: Display release details for approval | |
| env: | |
| CHANGELOG_CONTENT: ${{ needs.prepare-release.outputs.changelog }} | |
| run: | | |
| cat >> $GITHUB_STEP_SUMMARY << SUMMARY | |
| ## 🚀 Release Approval Required | |
| ### Version Bump | |
| | Current | → | New | | |
| |---------|---|-----| | |
| | v${{ needs.prepare-release.outputs.current_version }} | → | **v${{ needs.prepare-release.outputs.version }}** | | |
| ### Build Status | |
| - ✅ Security scan (Trivy) passed | |
| - ✅ Python unit tests passed | |
| - ✅ Console unit tests passed | |
| - ✅ Console build & typecheck passed | |
| - ✅ Linux x86_64 build ready | |
| - ✅ Linux arm64 build ready | |
| - ✅ Darwin x86_64 build ready | |
| - ✅ Darwin arm64 build ready | |
| ### Changelog for v${{ needs.prepare-release.outputs.version }} | |
| SUMMARY | |
| # Write changelog safely via environment variable | |
| printf '%s\n' "$CHANGELOG_CONTENT" >> $GITHUB_STEP_SUMMARY | |
| cat >> $GITHUB_STEP_SUMMARY << 'SUMMARY' | |
| --- | |
| **Approve this deployment to publish the release.** | |
| SUMMARY | |
| - name: Release approved | |
| run: | | |
| echo "✅ Release v${{ needs.prepare-release.outputs.version }} approved!" | |
| echo "Proceeding to publish..." | |
| # Create release and upload all artifacts only after approval | |
| publish-release: | |
| name: Publish Release | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| id-token: write | |
| attestations: write | |
| runs-on: ubuntu-latest | |
| needs: | |
| - prepare-release | |
| - approve-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Sync with remote before release | |
| if: github.event_name != 'workflow_dispatch' | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git fetch origin main | |
| git reset --hard origin/main | |
| - name: Install git-crypt | |
| run: sudo apt-get update && sudo apt-get install -y git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| path: artifacts | |
| - name: List artifacts | |
| run: | | |
| echo "Downloaded artifacts:" | |
| find artifacts -type f -ls | |
| - name: Attest build provenance | |
| uses: actions/attest-build-provenance@43d14bc2b83dec42d39ecae14e916627a18bb661 # v3 | |
| with: | |
| subject-path: | | |
| artifacts/pilot-linux-x86_64/pilot-linux-x86_64.so | |
| artifacts/pilot-linux-arm64/pilot-linux-arm64.so | |
| artifacts/pilot-darwin-x86_64/pilot-darwin-x86_64.so | |
| artifacts/pilot-darwin-arm64/pilot-darwin-arm64.so | |
| artifacts/pilot-linux-x86_64/pilot | |
| - name: Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 | |
| with: | |
| node-version: "22" | |
| - name: Prepend new release to CHANGELOG.md with git-cliff | |
| if: ${{ github.event.inputs.changelog == '' }} | |
| uses: orhun/git-cliff-action@e16f179f0be49ecdfe63753837f20b9531642772 # v4 | |
| with: | |
| config: cliff.toml | |
| args: --unreleased --tag v${{ needs.prepare-release.outputs.version }} --prepend CHANGELOG.md | |
| env: | |
| GITHUB_REPO: ${{ github.repository }} | |
| - name: Use custom changelog if provided | |
| if: ${{ github.event.inputs.changelog != '' }} | |
| env: | |
| CHANGELOG: ${{ github.event.inputs.changelog }} | |
| run: | | |
| echo "$CHANGELOG" > CHANGELOG.md | |
| echo "Using custom changelog content" | |
| - name: Create release with semantic-release | |
| if: github.event_name != 'workflow_dispatch' | |
| id: semantic | |
| uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0 | |
| with: | |
| extra_plugins: | | |
| @semantic-release/git | |
| @semantic-release/exec | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Update version files for manual trigger | |
| if: github.event_name == 'workflow_dispatch' | |
| run: | | |
| VERSION="${{ needs.prepare-release.outputs.version }}" | |
| echo "Updating version files to ${VERSION}..." | |
| # Update version in Python files (same as semantic-release prepareCmd) | |
| sed -i 's/^__version__ = ".*"/__version__ = "'"${VERSION}"'"/' installer/__init__.py launcher/__init__.py | |
| # Update version in README.md | |
| sed -i "s/export VERSION=[0-9.]*/export VERSION=${VERSION}/g" README.md | |
| echo "Version files updated:" | |
| grep __version__ installer/__init__.py launcher/__init__.py | |
| grep "VERSION=" README.md | head -1 | |
| - name: Commit and push version updates for manual trigger | |
| if: github.event_name == 'workflow_dispatch' | |
| run: | | |
| VERSION="${{ needs.prepare-release.outputs.version }}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # Stage all updated files | |
| git add installer/__init__.py launcher/__init__.py README.md CHANGELOG.md | |
| # Check if there are changes to commit | |
| if git diff --staged --quiet; then | |
| echo "No changes to commit" | |
| else | |
| git commit -m "chore(release): ${VERSION} [skip ci]" | |
| git push origin main | |
| echo "Version updates committed and pushed" | |
| fi | |
| - name: Create release for manual trigger | |
| if: github.event_name == 'workflow_dispatch' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ needs.prepare-release.outputs.version }}" | |
| if ! gh release view "v${VERSION}" >/dev/null 2>&1; then | |
| echo "Creating release v${VERSION}..." | |
| gh release create "v${VERSION}" --title "v${VERSION}" --generate-notes | |
| fi | |
| - name: Generate tree.json manifest | |
| run: | | |
| echo "Generating tree.json from repository files..." | |
| git ls-tree -r HEAD | python3 -c " | |
| import sys, json | |
| items = [] | |
| for line in sys.stdin: | |
| parts = line.strip().split('\t', 1) | |
| if len(parts) == 2: | |
| meta, path = parts | |
| fields = meta.split() | |
| if len(fields) == 3: | |
| items.append({'path': path, 'type': 'blob', 'sha': fields[2]}) | |
| json.dump({'tree': items}, sys.stdout, separators=(', ', ': ')) | |
| " > tree.json | |
| echo "Validating tree.json..." | |
| python3 -c "import json; data=json.load(open('tree.json')); assert 'tree' in data and len(data['tree']) > 0, 'Invalid tree.json'" | |
| echo "tree.json generated successfully with $(python3 -c "import json; print(len(json.load(open('tree.json'))['tree']))") files" | |
| - name: Upload artifacts to release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ needs.prepare-release.outputs.version }}" | |
| echo "Uploading artifacts for v${VERSION}" | |
| # Wait for release to exist with retry logic | |
| MAX_RETRIES=12 | |
| RETRY_DELAY=5 | |
| for i in $(seq 1 $MAX_RETRIES); do | |
| if gh release view "v${VERSION}" >/dev/null 2>&1; then | |
| echo "Release v${VERSION} found" | |
| break | |
| fi | |
| if [ $i -eq $MAX_RETRIES ]; then | |
| echo "Release v${VERSION} not found after ${MAX_RETRIES} retries" | |
| echo "Creating release manually..." | |
| gh release create "v${VERSION}" --title "v${VERSION}" --notes "Release v${VERSION}" | |
| fi | |
| echo "Waiting for release... (attempt $i/$MAX_RETRIES)" | |
| sleep $RETRY_DELAY | |
| done | |
| # Upload all .so files and tree.json | |
| gh release upload "v${VERSION}" \ | |
| artifacts/pilot-linux-x86_64/pilot-linux-x86_64.so \ | |
| artifacts/pilot-linux-arm64/pilot-linux-arm64.so \ | |
| artifacts/pilot-darwin-x86_64/pilot-darwin-x86_64.so \ | |
| artifacts/pilot-darwin-arm64/pilot-darwin-arm64.so \ | |
| artifacts/pilot-linux-x86_64/pilot \ | |
| tree.json \ | |
| --clobber | |
| echo "All artifacts uploaded successfully" | |
| - name: Output release info | |
| run: | | |
| echo "Released version: ${{ needs.prepare-release.outputs.version }}" | |
| echo "All platform binaries are now available" | |
| # Deploy website to production in parallel with publish-release (both after approval) | |
| deploy-website: | |
| name: Deploy Website (Production) | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| needs: | |
| - prepare-release | |
| - approve-release | |
| if: needs.prepare-release.outputs.should_release == 'true' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install git-crypt | |
| run: sudo apt-get update && sudo apt-get install -y git-crypt | |
| - name: Unlock repository | |
| env: | |
| GIT_CRYPT_KEY: ${{ secrets.GIT_CRYPT_KEY }} | |
| run: bash .github/workflows/scripts/setup-git-crypt.sh | |
| - name: Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6 | |
| with: | |
| node-version: "22" | |
| - name: Install Vercel CLI | |
| run: npm install -g vercel | |
| - name: Deploy to Vercel (Production) | |
| env: | |
| VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} | |
| VERCEL_ORG_ID: team_jAsHrk71vRyWK6bCTYGJyp0q | |
| VERCEL_PROJECT_ID: prj_TXccrJI83HyNvQUZxqStUFgus9NB | |
| run: | | |
| DEPLOY_URL=$(vercel deploy --token=$VERCEL_TOKEN --prod) | |
| echo "Deployed to: $DEPLOY_URL" | |