feat: add Cursor and verified OpenCode support #15
Workflow file for this run
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: | ||
| tags: ["v*"] | ||
| pull_request: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
| permissions: | ||
| contents: read | ||
| jobs: | ||
| validate: | ||
| runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Validate tag and version | ||
| shell: bash | ||
| run: | | ||
| if [ "$GITHUB_REF_TYPE" = "tag" ]; then test "$GITHUB_REF_NAME" = "v$(cat VERSION)"; fi | ||
| python3 -m unittest discover -s tests -v | ||
| python3 -m py_compile core/*.py scripts/*.py scripts/tools/*.py tests/*.py | ||
| sh -n install.sh scripts/*.sh pages/install.sh cloudflare/deploy.sh | ||
| python3 scripts/sync-web-assets.py --check | ||
| node --check cloudflare/worker.js | ||
| online: | ||
| runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build online packages | ||
| run: | | ||
| cp install.sh pages/install.sh | ||
| cp scripts/install.ps1 pages/install.ps1 | ||
| python3 scripts/build-online.py | ||
| cp install.sh scripts/install.ps1 VERSION pages/ | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: online | ||
| path: | | ||
| pages/agentboot-online-* | ||
| pages/install.sh | ||
| pages/install.ps1 | ||
| pages/VERSION | ||
| offline-linux: | ||
| runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build verified Codex offline package | ||
| run: AGENTS=codex PLATFORMS=linux-x64 TAG="v$(cat VERSION)" sh scripts/build-offline.sh | ||
| - name: Smoke install, execute, and uninstall | ||
| shell: bash | ||
| run: | | ||
| root="$(mktemp -d)" | ||
| mkdir -p "$root/extract" "$root/home" | ||
| tag="v$(cat VERSION)" | ||
| tar -xzf "dist/AgentBoot-offline-${tag}-linux-x64.tar.gz" -C "$root/extract" | ||
| app="$root/extract/AgentBoot" | ||
| HOME="$root/home" sh "$app/install-offline.sh" codex | ||
| AGENTBOOT_HOME="$root/home/.agentboot" HOME="$root/home" "$root/home/.agentboot/bin/codex" --version | ||
| AGENTBOOT_HOME="$root/home/.agentboot" HOME="$root/home" python3 "$root/home/.agentboot/app/core/menu.py" uninstall codex | ||
| test ! -e "$root/home/.agentboot/agents/codex" | ||
| mv "dist/AgentBoot-offline-${tag}-linux-x64.tar.gz" "dist/AgentBoot-offline-${tag}-linux-x64-codex.tar.gz" | ||
| mv "dist/AgentBoot-offline-${tag}-linux-x64-sfx.sh" "dist/AgentBoot-offline-${tag}-linux-x64-codex-sfx.sh" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: offline-linux | ||
| path: dist/AgentBoot-offline-*-linux-x64-codex* | ||
| offline-windows: | ||
| runs-on: windows-latest | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build verified Codex offline package | ||
| shell: powershell | ||
| run: .\scripts\build-offline.ps1 -Tag ('v' + (Get-Content VERSION -Raw).Trim()) -Platforms win-x64 -Agents codex | ||
| - name: Smoke install, execute, and uninstall | ||
| shell: powershell | ||
| run: | | ||
| $root = Join-Path $env:RUNNER_TEMP 'agentboot-smoke' | ||
| $extract = Join-Path $root 'extract' | ||
| $smokeHome = Join-Path $root '测试-home' | ||
| New-Item -ItemType Directory -Path $extract, $smokeHome -Force | Out-Null | ||
| $tag = 'v' + (Get-Content VERSION -Raw).Trim() | ||
| tar -xf "dist\AgentBoot-offline-$tag-win-x64.zip" -C $extract | ||
| $app = Join-Path $extract 'AgentBoot' | ||
| $env:AGENTBOOT_HOME = Join-Path $smokeHome '.agentboot' | ||
| $env:USERPROFILE = $smokeHome | ||
| $env:LOCALAPPDATA = Join-Path $smokeHome 'LocalAppData' | ||
| & "$app\install-offline.ps1" -Agents codex | ||
| & "$smokeHome\.agentboot\bin\codex.cmd" --version | ||
| python "$env:LOCALAPPDATA\AgentBoot\app\core\menu.py" uninstall codex | ||
| if (Test-Path "$smokeHome\.agentboot\agents\codex") { throw 'Codex payload not removed' } | ||
| Move-Item "dist\AgentBoot-offline-$tag-win-x64.zip" "dist\AgentBoot-offline-$tag-win-x64-codex.zip" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: offline-windows | ||
| path: dist/AgentBoot-offline-*-win-x64-codex.zip | ||
| macos-smoke: | ||
| runs-on: macos-15-intel | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build and smoke native macOS Codex package | ||
| shell: bash | ||
| run: | | ||
| AGENTS=codex PLATFORMS=darwin-x64 TAG="v$(cat VERSION)" sh scripts/build-offline.sh | ||
| root="$(mktemp -d)" | ||
| mkdir -p "$root/extract" "$root/home" | ||
| tag="v$(cat VERSION)" | ||
| tar -xzf "dist/AgentBoot-offline-${tag}-darwin-x64.tar.gz" -C "$root/extract" | ||
| HOME="$root/home" sh "$root/extract/AgentBoot/install-offline.sh" codex | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" "$root/home/.agentboot/bin/codex" --version | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 "$root/home/.agentboot/app/core/menu.py" uninstall codex | ||
| test ! -e "$root/home/.agentboot/agents/codex" | ||
| extended-linux: | ||
| runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} | ||
| env: | ||
| TMPDIR: ${{ runner.temp }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build and smoke OpenCode Linux offline package | ||
| shell: bash | ||
| run: | | ||
| AGENTS=opencode PLATFORMS=linux-x64 TAG="v$(cat VERSION)" sh scripts/build-offline.sh | ||
| root="$(mktemp -d)" | ||
| mkdir -p "$root/extract" "$root/home" | ||
| tag="v$(cat VERSION)" | ||
| tar -xzf "dist/AgentBoot-offline-${tag}-linux-x64.tar.gz" -C "$root/extract" | ||
| app="$root/extract/AgentBoot" | ||
| HOME="$root/home" sh "$app/install-offline.sh" opencode | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" "$root/home/.agentboot/bin/opencode" --version | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 "$root/home/.agentboot/app/core/menu.py" uninstall opencode | ||
| test ! -e "$root/home/.agentboot/agents/opencode" | ||
| test -f "$root/home/.config/opencode/opencode.json" | ||
| mv "dist/AgentBoot-offline-${tag}-linux-x64.tar.gz" "dist/AgentBoot-offline-${tag}-linux-x64-opencode.tar.gz" | ||
| mv "dist/AgentBoot-offline-${tag}-linux-x64-sfx.sh" "dist/AgentBoot-offline-${tag}-linux-x64-opencode-sfx.sh" | ||
| - name: Install verify and uninstall official Cursor AppImage | ||
| shell: bash | ||
| run: | | ||
| root="$(mktemp -d)" | ||
| HOME="$root" AGENTBOOT_HOME="$root/.agentboot" python3 core/menu.py install cursor | ||
| HOME="$root" "$root/.agentboot/apps/cursor/Cursor.AppImage" --appimage-version | ||
| HOME="$root" AGENTBOOT_HOME="$root/.agentboot" python3 core/menu.py uninstall cursor | ||
| test ! -e "$root/.agentboot/apps/cursor" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: extended-linux | ||
| path: dist/AgentBoot-offline-*-linux-x64-opencode* | ||
| extended-windows: | ||
| runs-on: windows-latest | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build and smoke OpenCode Windows offline package | ||
| shell: powershell | ||
| run: | | ||
| $tag = 'v' + (Get-Content VERSION -Raw).Trim() | ||
| .\scripts\build-offline.ps1 -Tag $tag -Platforms win-x64 -Agents opencode | ||
| $root = Join-Path $env:RUNNER_TEMP 'opencode-smoke' | ||
| $extract = Join-Path $root 'extract' | ||
| $opencodeHome = Join-Path $root 'home' | ||
| New-Item -ItemType Directory -Path $extract, $opencodeHome -Force | Out-Null | ||
| tar -xf "dist\AgentBoot-offline-$tag-win-x64.zip" -C $extract | ||
| $app = Join-Path $extract 'AgentBoot' | ||
| $env:AGENTBOOT_HOME = Join-Path $opencodeHome '.agentboot' | ||
| $env:USERPROFILE = $opencodeHome | ||
| $env:LOCALAPPDATA = Join-Path $opencodeHome 'LocalAppData' | ||
| & "$app\install-offline.ps1" -Agents opencode | ||
| & "$opencodeHome\.agentboot\bin\opencode.cmd" --version | ||
| python "$env:LOCALAPPDATA\AgentBoot\app\core\menu.py" uninstall opencode | ||
| if (Test-Path "$opencodeHome\.agentboot\agents\opencode") { throw 'OpenCode payload not removed' } | ||
| if (-not (Test-Path "$opencodeHome\.config\opencode\opencode.json")) { throw 'OpenCode config was not preserved' } | ||
| Move-Item "dist\AgentBoot-offline-$tag-win-x64.zip" "dist\AgentBoot-offline-$tag-win-x64-opencode.zip" | ||
| - name: Install verify and uninstall official Cursor user app | ||
| shell: powershell | ||
| run: | | ||
| $root = Join-Path $env:RUNNER_TEMP 'cursor-smoke' | ||
| New-Item -ItemType Directory -Path $root -Force | Out-Null | ||
| $env:AGENTBOOT_HOME = Join-Path $root '.agentboot' | ||
| $env:USERPROFILE = $root | ||
| python core/menu.py install cursor | ||
| $exe = Join-Path $root '.agentboot\apps\cursor\Cursor.exe' | ||
| if (-not (Test-Path $exe)) { throw 'Cursor.exe missing' } | ||
| $signature = Get-AuthenticodeSignature -LiteralPath $exe | ||
| if ($signature.Status -ne 'Valid') { throw 'Cursor.exe signature invalid' } | ||
| python core/menu.py uninstall cursor | ||
| if (Test-Path (Join-Path $root '.agentboot\apps\cursor')) { throw 'Cursor managed app not removed' } | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: extended-windows | ||
| path: dist/AgentBoot-offline-*-win-x64-opencode.zip | ||
| extended-macos-x64: | ||
| runs-on: macos-15-intel | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build and smoke OpenCode plus Cursor on Intel macOS | ||
| shell: bash | ||
| run: | | ||
| AGENTS=opencode PLATFORMS=darwin-x64 TAG="v$(cat VERSION)" sh scripts/build-offline.sh | ||
| root="$(mktemp -d)"; mkdir -p "$root/extract" "$root/home" | ||
| tag="v$(cat VERSION)"; tar -xzf "dist/AgentBoot-offline-${tag}-darwin-x64.tar.gz" -C "$root/extract" | ||
| HOME="$root/home" sh "$root/extract/AgentBoot/install-offline.sh" opencode | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" "$root/home/.agentboot/bin/opencode" --version | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 "$root/home/.agentboot/app/core/menu.py" uninstall opencode | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 core/menu.py install cursor | ||
| test -d "$root/home/.agentboot/apps/cursor/Cursor.app" | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 core/menu.py uninstall cursor | ||
| test ! -e "$root/home/.agentboot/apps/cursor" | ||
| mv "dist/AgentBoot-offline-${tag}-darwin-x64.tar.gz" "dist/AgentBoot-offline-${tag}-darwin-x64-opencode.tar.gz" | ||
| mv "dist/AgentBoot-offline-${tag}-darwin-x64-sfx.sh" "dist/AgentBoot-offline-${tag}-darwin-x64-opencode-sfx.sh" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: extended-macos-x64 | ||
| path: dist/AgentBoot-offline-*-darwin-x64-opencode* | ||
| extended-macos-arm64: | ||
| runs-on: macos-15 | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Build and smoke OpenCode plus Cursor on Apple Silicon | ||
| shell: bash | ||
| run: | | ||
| test "$(uname -m)" = arm64 | ||
| AGENTS=opencode PLATFORMS=darwin-arm64 TAG="v$(cat VERSION)" sh scripts/build-offline.sh | ||
| root="$(mktemp -d)"; mkdir -p "$root/extract" "$root/home" | ||
| tag="v$(cat VERSION)"; tar -xzf "dist/AgentBoot-offline-${tag}-darwin-arm64.tar.gz" -C "$root/extract" | ||
| HOME="$root/home" sh "$root/extract/AgentBoot/install-offline.sh" opencode | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" "$root/home/.agentboot/bin/opencode" --version | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 "$root/home/.agentboot/app/core/menu.py" uninstall opencode | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 core/menu.py install cursor | ||
| test -d "$root/home/.agentboot/apps/cursor/Cursor.app" | ||
| HOME="$root/home" AGENTBOOT_HOME="$root/home/.agentboot" python3 core/menu.py uninstall cursor | ||
| test ! -e "$root/home/.agentboot/apps/cursor" | ||
| mv "dist/AgentBoot-offline-${tag}-darwin-arm64.tar.gz" "dist/AgentBoot-offline-${tag}-darwin-arm64-opencode.tar.gz" | ||
| mv "dist/AgentBoot-offline-${tag}-darwin-arm64-sfx.sh" "dist/AgentBoot-offline-${tag}-darwin-arm64-opencode-sfx.sh" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: extended-macos-arm64 | ||
| path: dist/AgentBoot-offline-*-darwin-arm64-opencode* | ||
| publish: | ||
| needs: [validate, online, offline-linux, offline-windows, macos-smoke, extended-linux, extended-windows, extended-macos-x64, extended-macos-arm64] | ||
| if: github.ref_type == 'tag' | ||
| runs-on: ${{ vars.AGENTBOOT_LINUX_RUNNER || 'ubuntu-latest' }} | ||
| environment: release-production | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | ||
| with: | ||
| path: release | ||
| merge-multiple: true | ||
| - name: Generate checksums | ||
| run: (cd release && find . -maxdepth 1 -type f ! -name SHA256SUMS.txt -print0 | sort -z | xargs -0 sha256sum > SHA256SUMS.txt) | ||
| - name: Publish GitHub Release | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then | ||
| gh release upload "$GITHUB_REF_NAME" release/* --repo "$GITHUB_REPOSITORY" --clobber | ||
| gh release edit "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --prerelease --latest=false | ||
| else | ||
| gh release create "$GITHUB_REF_NAME" release/* \ | ||
| --repo "$GITHUB_REPOSITORY" \ | ||
| --title "AgentBoot $GITHUB_REF_NAME" \ | ||
| --prerelease \ | ||
| --generate-notes \ | ||
| --verify-tag | ||
| fi | ||
| - name: Wait for Pages deployment | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| for attempt in $(seq 1 30); do | ||
| row=$(gh run list --repo "$GITHUB_REPOSITORY" --workflow deploy-pages --branch main --limit 10 \ | ||
| --json headSha,conclusion,status -q ".[] | select(.headSha == \"$GITHUB_SHA\") | [.status,.conclusion] | @tsv" | head -n 1) | ||
| status=$(printf '%s' "$row" | cut -f1) | ||
| conclusion=$(printf '%s' "$row" | cut -f2) | ||
| [ "$status" = completed ] && [ "$conclusion" = success ] && exit 0 | ||
| [ "$status" = completed ] && [ "$conclusion" = failure ] && exit 1 | ||
| sleep 10 | ||
| done | ||
| exit 1 | ||
| - name: Wait for primary and mirror endpoints | ||
| run: | | ||
| for attempt in $(seq 1 60); do | ||
| python3 scripts/verify-live-release.py && exit 0 | ||
| sleep 10 | ||
| done | ||
| exit 1 | ||
| - name: Promote verified release | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: gh release edit "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" --prerelease=false --latest | ||