fix: cross-target path mapping for skills/agents in apm pack (#426)
#655
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: CI/CD Pipeline | |
| env: | |
| PYTHON_VERSION: '3.12' # Standardize on 3.12 for Ubuntu 24.04 LTS compatibility | |
| on: | |
| push: | |
| branches: [ main ] | |
| tags: [ "v*" ] | |
| paths-ignore: | |
| - 'docs/**' | |
| - '.gitignore' | |
| - 'LICENSE' | |
| schedule: | |
| # Run daily at 04:00 UTC (6 AM CEST) | |
| - cron: '0 4 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| test_build: | |
| description: 'Test build (uploads as workflow artifacts instead of release assets)' | |
| required: false | |
| default: true | |
| type: boolean | |
| # Restrict default GITHUB_TOKEN permissions for all jobs (principle of least privilege) | |
| permissions: | |
| contents: read | |
| jobs: | |
| # Unit tests + binary build combined (Linux + Windows). | |
| # Merging test+build eliminates ~1.5m runner re-provisioning overhead per platform. | |
| # macOS runners are scarce and have their own consolidated jobs below. | |
| build-and-test: | |
| name: Build & Test | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-24.04 | |
| arch: x86_64 | |
| platform: linux | |
| binary_name: apm-linux-x86_64 | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| platform: linux | |
| binary_name: apm-linux-arm64 | |
| - os: windows-latest | |
| arch: x86_64 | |
| platform: windows | |
| binary_name: apm-windows-x86_64 | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --extra dev --extra build | |
| - name: Run tests | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GH_MODELS_PAT }} | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| run: uv run pytest tests/unit tests/test_console.py tests/integration/test_runtime_smoke.py -n auto --dist worksteal | |
| - name: Install UPX (Linux) | |
| if: matrix.platform == 'linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y upx-ucl | |
| - name: Build binary (Unix) | |
| if: matrix.platform != 'windows' | |
| run: | | |
| chmod +x scripts/build-binary.sh | |
| uv run ./scripts/build-binary.sh | |
| - name: Build binary (Windows) | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| run: | | |
| uv run pwsh scripts/windows/build-binary.ps1 | |
| - name: Upload binary as workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.binary_name }} | |
| path: | | |
| ./dist/${{ matrix.binary_name }} | |
| ./dist/${{ matrix.binary_name }}.sha256 | |
| ./scripts/test-release-validation.sh | |
| ./scripts/windows/test-release-validation.ps1 | |
| ./scripts/test-dependency-integration.sh | |
| ./scripts/windows/test-dependency-integration.ps1 | |
| ./scripts/github-token-helper.sh | |
| ./scripts/windows/github-token-helper.ps1 | |
| include-hidden-files: true # Required to include .apm directories | |
| retention-days: 30 | |
| if-no-files-found: error | |
| # Consolidated macOS Intel build + validation. | |
| # Intel runners are plentiful (<1 min queue) so this runs on every push for | |
| # early macOS build-regression feedback. Integration and release-validation | |
| # phases are conditional on tag/schedule/dispatch. | |
| # Root node — runs its own unit tests instead of waiting for build-and-test. | |
| build-and-validate-macos-intel: | |
| name: Build & Validate (macOS x86_64) | |
| runs-on: macos-15-intel | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Setup build environment | |
| run: | | |
| sudo xcode-select --install 2>/dev/null || true | |
| until xcode-select -p >/dev/null 2>&1; do sleep 5; done | |
| - name: Install UPX | |
| run: brew install upx | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --extra dev --extra build | |
| - name: Run unit tests | |
| run: uv run pytest tests/unit tests/test_console.py -n auto --dist worksteal | |
| # ── PHASE 1: BUILD BINARY ── | |
| - name: Build binary | |
| run: | | |
| chmod +x scripts/build-binary.sh | |
| uv run ./scripts/build-binary.sh | |
| - name: Upload binary as workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: apm-darwin-x86_64 | |
| path: | | |
| ./dist/apm-darwin-x86_64 | |
| ./dist/apm-darwin-x86_64.sha256 | |
| ./scripts/test-release-validation.sh | |
| ./scripts/test-dependency-integration.sh | |
| ./scripts/github-token-helper.sh | |
| include-hidden-files: true | |
| retention-days: 30 | |
| if-no-files-found: error | |
| # ── PHASE 2: INTEGRATION TESTS (tag/schedule/dispatch only) ── | |
| - name: Run integration tests | |
| if: github.ref_type == 'tag' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| chmod +x scripts/test-integration.sh | |
| uv run ./scripts/test-integration.sh | |
| timeout-minutes: 20 | |
| # ── PHASE 3: RELEASE VALIDATION (tag/schedule/dispatch only) ── | |
| - name: Prepare isolated release-validation environment | |
| if: github.ref_type == 'tag' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| run: | | |
| mkdir -p /tmp/apm-isolated-test/dist | |
| cp -R ./dist/apm-darwin-x86_64 /tmp/apm-isolated-test/dist/ | |
| cp ./dist/apm-darwin-x86_64.sha256 /tmp/apm-isolated-test/dist/ 2>/dev/null || true | |
| cp ./scripts/test-release-validation.sh /tmp/apm-isolated-test/ | |
| cp ./scripts/test-dependency-integration.sh /tmp/apm-isolated-test/ 2>/dev/null || true | |
| cp ./scripts/github-token-helper.sh /tmp/apm-isolated-test/ 2>/dev/null || true | |
| cd /tmp/apm-isolated-test | |
| chmod +x ./dist/apm-darwin-x86_64/apm | |
| ln -s "$(pwd)/dist/apm-darwin-x86_64/apm" "$(pwd)/apm" | |
| echo "/tmp/apm-isolated-test" >> $GITHUB_PATH | |
| - name: Run release validation tests | |
| if: github.ref_type == 'tag' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| chmod +x test-release-validation.sh | |
| ./test-release-validation.sh | |
| timeout-minutes: 20 | |
| # Consolidated macOS ARM build + validation. | |
| # ARM runners (macos-latest) are extremely scarce — 2-4+ hour queue waits are | |
| # common. This job is gated to tag/schedule/dispatch only so push-to-main never | |
| # blocks on ARM availability. All phases run unconditionally since the job itself | |
| # is already release-gated. | |
| # Root node — runs its own unit tests instead of waiting for build-and-test. | |
| build-and-validate-macos-arm: | |
| name: Build & Validate (macOS arm64) | |
| if: github.ref_type == 'tag' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: macos-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install UPX | |
| run: brew install upx | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --extra dev --extra build | |
| - name: Run unit tests | |
| run: uv run pytest tests/unit tests/test_console.py -n auto --dist worksteal | |
| # ── PHASE 1: BUILD BINARY ── | |
| - name: Build binary | |
| run: | | |
| chmod +x scripts/build-binary.sh | |
| uv run ./scripts/build-binary.sh | |
| - name: Upload binary as workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: apm-darwin-arm64 | |
| path: | | |
| ./dist/apm-darwin-arm64 | |
| ./dist/apm-darwin-arm64.sha256 | |
| ./scripts/test-release-validation.sh | |
| ./scripts/test-dependency-integration.sh | |
| ./scripts/github-token-helper.sh | |
| include-hidden-files: true | |
| retention-days: 30 | |
| if-no-files-found: error | |
| # ── PHASE 2: INTEGRATION TESTS ── | |
| - name: Run integration tests | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| chmod +x scripts/test-integration.sh | |
| uv run ./scripts/test-integration.sh | |
| timeout-minutes: 20 | |
| # ── PHASE 3: RELEASE VALIDATION ── | |
| - name: Prepare isolated release-validation environment | |
| run: | | |
| mkdir -p /tmp/apm-isolated-test/dist | |
| cp -R ./dist/apm-darwin-arm64 /tmp/apm-isolated-test/dist/ | |
| cp ./dist/apm-darwin-arm64.sha256 /tmp/apm-isolated-test/dist/ 2>/dev/null || true | |
| cp ./scripts/test-release-validation.sh /tmp/apm-isolated-test/ | |
| cp ./scripts/test-dependency-integration.sh /tmp/apm-isolated-test/ 2>/dev/null || true | |
| cp ./scripts/github-token-helper.sh /tmp/apm-isolated-test/ 2>/dev/null || true | |
| cd /tmp/apm-isolated-test | |
| chmod +x ./dist/apm-darwin-arm64/apm | |
| ln -s "$(pwd)/dist/apm-darwin-arm64/apm" "$(pwd)/apm" | |
| echo "/tmp/apm-isolated-test" >> $GITHUB_PATH | |
| - name: Run release validation tests | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| chmod +x test-release-validation.sh | |
| ./test-release-validation.sh | |
| timeout-minutes: 20 | |
| # Integration tests with full source code access (Linux + Windows). | |
| # macOS integration tests run inside the consolidated macOS jobs to avoid re-queuing scarce runners. | |
| # Skip on push-to-main: already validated by ci-integration.yml during the PR. | |
| # Run on tags (release gate), schedule (regression), and dispatch (manual). | |
| integration-tests: | |
| name: Integration Tests | |
| if: github.ref_type == 'tag' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| needs: [build-and-test] | |
| strategy: | |
| matrix: | |
| include: | |
| - os: ubuntu-24.04 | |
| arch: x86_64 | |
| platform: linux | |
| binary_name: apm-linux-x86_64 | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| platform: linux | |
| binary_name: apm-linux-arm64 | |
| - os: windows-latest | |
| arch: x86_64 | |
| platform: windows | |
| binary_name: apm-windows-x86_64 | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download APM binary from build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ matrix.binary_name }} | |
| path: ./ | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| with: | |
| enable-cache: true | |
| - name: Install test dependencies | |
| run: uv sync --extra dev | |
| - name: Run integration tests (Unix) | |
| if: matrix.platform != 'windows' | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} # Primary: APM module access | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} # Azure DevOps module access | |
| run: | | |
| chmod +x scripts/test-integration.sh | |
| uv run ./scripts/test-integration.sh | |
| timeout-minutes: 20 | |
| - name: Run integration tests (Windows) | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| uv run pwsh scripts/windows/test-integration.ps1 -SkipBuild | |
| timeout-minutes: 20 | |
| # Release validation tests - Final pre-release validation of shipped binary (Linux + Windows). | |
| # macOS release validation runs inside the consolidated macOS jobs. | |
| release-validation: | |
| name: Release Validation | |
| if: github.ref_type == 'tag' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| needs: [build-and-test, integration-tests] | |
| strategy: | |
| matrix: | |
| include: | |
| - os: ubuntu-24.04 | |
| arch: x86_64 | |
| platform: linux | |
| binary_name: apm-linux-x86_64 | |
| - os: ubuntu-24.04-arm | |
| arch: arm64 | |
| platform: linux | |
| binary_name: apm-linux-arm64 | |
| - os: windows-latest | |
| arch: x86_64 | |
| platform: windows | |
| binary_name: apm-windows-x86_64 | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '24' | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Download APM binary from build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ matrix.binary_name }} | |
| path: ${{ matrix.platform == 'windows' && 'D:\apm-isolated-test' || '/tmp/apm-isolated-test/' }} | |
| - name: Make binary executable and verify isolation (Unix) | |
| if: matrix.platform != 'windows' | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| # Debug: List the downloaded structure | |
| echo "Downloaded structure:" | |
| find . -name "apm" -type f | |
| ls -la ./dist/ | |
| # Make the binary executable | |
| chmod +x ./dist/${{ matrix.binary_name }}/apm | |
| - name: Create APM symlink for testing (Unix) | |
| if: matrix.platform != 'windows' | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| ln -s "$(pwd)/dist/${{ matrix.binary_name }}/apm" "$(pwd)/apm" | |
| echo "/tmp/apm-isolated-test" >> $GITHUB_PATH | |
| - name: Verify binary and add to PATH (Windows) | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| run: | | |
| cd D:\apm-isolated-test | |
| # Debug: List the downloaded structure | |
| Write-Host "Downloaded structure:" | |
| Get-ChildItem -Recurse -Filter "apm.exe" | |
| Get-ChildItem .\dist\ | |
| # Add binary directory to PATH | |
| $binDir = "D:\apm-isolated-test\dist\${{ matrix.binary_name }}" | |
| echo $binDir | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| - name: Run release validation tests (Unix) | |
| if: matrix.platform != 'windows' | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| cd /tmp/apm-isolated-test | |
| chmod +x scripts/test-release-validation.sh | |
| ./scripts/test-release-validation.sh | |
| timeout-minutes: 20 | |
| - name: Run release validation tests (Windows) | |
| if: matrix.platform == 'windows' | |
| shell: pwsh | |
| env: | |
| APM_E2E_TESTS: "1" | |
| GITHUB_APM_PAT: ${{ secrets.GH_CLI_PAT }} | |
| ADO_APM_PAT: ${{ secrets.ADO_APM_PAT }} | |
| run: | | |
| cd D:\apm-isolated-test | |
| .\scripts\windows\test-release-validation.ps1 | |
| timeout-minutes: 20 | |
| create-release: | |
| name: Create GitHub Release | |
| needs: [build-and-test, build-and-validate-macos-intel, build-and-validate-macos-arm, integration-tests, release-validation] | |
| if: github.ref_type == 'tag' # All tags create GitHub releases | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # Required for release creation | |
| outputs: | |
| is_prerelease: ${{ steps.release_type.outputs.is_prerelease }} | |
| is_private_repo: ${{ github.event.repository.private }} | |
| steps: | |
| - name: Download all build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: ./dist | |
| - name: Prepare release binaries | |
| run: | | |
| # Debug: Show the actual downloaded structure | |
| echo "Directory listing:" | |
| ls -la ./dist | |
| echo "" | |
| # Create tar.gz archives from directory structure for release and Homebrew | |
| cd dist | |
| for binary in apm-linux-x86_64 apm-linux-arm64 apm-darwin-x86_64 apm-darwin-arm64; do | |
| # With artifacts containing both scripts and dist/, the binary is in artifact/dist/binary/ | |
| artifact_dir="${binary}" | |
| binary_dir="${artifact_dir}/dist/${binary}" | |
| if [ -d "$binary_dir" ] && [ -f "$binary_dir/apm" ]; then | |
| echo "Processing $binary_dir directory..." | |
| # Ensure the binary is executable before archiving | |
| chmod +x "${binary_dir}/apm" | |
| # Create tar.gz with preserved permissions, archiving ONLY the binary directory for release | |
| tar -czf "${binary}.tar.gz" -C "${artifact_dir}/dist" "${binary}" | |
| if command -v sha256sum &> /dev/null; then | |
| sha256sum "${binary}.tar.gz" > "${binary}.tar.gz.sha256" | |
| elif command -v shasum &> /dev/null; then | |
| shasum -a 256 "${binary}.tar.gz" > "${binary}.tar.gz.sha256" | |
| fi | |
| echo "Created ${binary}.tar.gz" | |
| else | |
| echo "ERROR: Binary directory $binary_dir not found or $binary_dir/apm missing" | |
| echo "Artifact directory contents:" | |
| ls -la "$artifact_dir/" || echo "Directory $artifact_dir does not exist" | |
| if [ -d "$artifact_dir/dist" ]; then | |
| echo "Dist directory contents:" | |
| ls -la "$artifact_dir/dist/" | |
| fi | |
| exit 1 | |
| fi | |
| done | |
| binary="apm-windows-x86_64" | |
| artifact_dir="${binary}" | |
| binary_dir="${artifact_dir}/dist/${binary}" | |
| if [ -d "$binary_dir" ] && [ -f "$binary_dir/apm.exe" ]; then | |
| echo "Processing $binary_dir directory..." | |
| ( | |
| cd "${artifact_dir}/dist" | |
| zip -qr "../../${binary}.zip" "${binary}" | |
| ) | |
| if command -v sha256sum &> /dev/null; then | |
| sha256sum "${binary}.zip" > "${binary}.zip.sha256" | |
| elif command -v shasum &> /dev/null; then | |
| shasum -a 256 "${binary}.zip" > "${binary}.zip.sha256" | |
| fi | |
| echo "Created ${binary}.zip" | |
| else | |
| echo "ERROR: Binary directory $binary_dir not found or $binary_dir/apm.exe missing" | |
| echo "Artifact directory contents:" | |
| ls -la "$artifact_dir/" || echo "Directory $artifact_dir does not exist" | |
| if [ -d "$artifact_dir/dist" ]; then | |
| echo "Dist directory contents:" | |
| ls -la "$artifact_dir/dist/" | |
| fi | |
| exit 1 | |
| fi | |
| - name: Determine release type | |
| id: release_type | |
| run: | | |
| TAG_NAME="${{ github.ref_name }}" | |
| # Check if tag matches stable semver pattern (e.g., v1.2.3, v0.2.0) | |
| # Stable: starts with v, followed by digits.digits.digits, then end of string | |
| if [[ "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "is_prerelease=false" >> $GITHUB_OUTPUT | |
| echo "Detected stable release: $TAG_NAME" | |
| # Check PEP 440 prerelease patterns: v1.2.3a1, v1.2.3b1, v1.2.3rc1, etc. | |
| elif [[ "$TAG_NAME" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(a|b|rc)[0-9]+$ ]]; then | |
| echo "is_prerelease=true" >> $GITHUB_OUTPUT | |
| echo "Detected PEP 440 prerelease: $TAG_NAME" | |
| else | |
| echo "is_prerelease=true" >> $GITHUB_OUTPUT | |
| echo "Detected other prerelease: $TAG_NAME" | |
| fi | |
| - name: Create GitHub Release | |
| id: release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| generate_release_notes: true | |
| prerelease: ${{ steps.release_type.outputs.is_prerelease == 'true' }} | |
| files: | | |
| ./dist/apm-linux-x86_64.tar.gz | |
| ./dist/apm-linux-x86_64.tar.gz.sha256 | |
| ./dist/apm-linux-arm64.tar.gz | |
| ./dist/apm-linux-arm64.tar.gz.sha256 | |
| ./dist/apm-darwin-x86_64.tar.gz | |
| ./dist/apm-darwin-x86_64.tar.gz.sha256 | |
| ./dist/apm-darwin-arm64.tar.gz | |
| ./dist/apm-darwin-arm64.tar.gz.sha256 | |
| ./dist/apm-windows-x86_64.zip | |
| ./dist/apm-windows-x86_64.zip.sha256 | |
| # GH-AW Compatibility — validates the released binary works in the | |
| # exact flow GitHub Agentic Workflows uses (isolated install + pack, no token). | |
| # Informational: runs as continue-on-error because it depends on external services | |
| # (GitHub API, npm, microsoft/apm-action, microsoft/apm-sample-package) that can | |
| # fail independently of APM code quality (~4% false-negative rate per execution). | |
| gh-aw-compat: | |
| name: GH-AW Compatibility | |
| needs: [create-release] | |
| if: github.ref_type == 'tag' | |
| runs-on: ubuntu-24.04 | |
| continue-on-error: true | |
| steps: | |
| - name: Install and pack with apm-action | |
| uses: microsoft/apm-action@v1 | |
| id: pack | |
| with: | |
| dependencies: | | |
| - microsoft/apm-sample-package | |
| isolated: 'true' | |
| pack: 'true' | |
| archive: 'true' | |
| target: claude | |
| apm-version: ${{ github.ref_name }} | |
| working-directory: /tmp/gh-aw-compat-test | |
| - name: Verify bundle | |
| run: | | |
| test -f "${{ steps.pack.outputs.bundle-path }}" | |
| echo "✅ GH-AW compatibility test passed" | |
| - name: Warn on failure | |
| if: failure() | |
| run: | | |
| echo "::warning::GH-AW compatibility test failed. This is informational — external dependency may be unavailable. Investigate before next release." | |
| # Publish to PyPI (only stable releases from public repo) | |
| publish-pypi: | |
| name: Publish to PyPI | |
| runs-on: ubuntu-latest | |
| needs: [build-and-test, build-and-validate-macos-intel, build-and-validate-macos-arm, integration-tests, release-validation, create-release] | |
| if: github.ref_type == 'tag' && needs.create-release.outputs.is_private_repo != 'true' && needs.create-release.outputs.is_prerelease != 'true' | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/apm-cli | |
| permissions: | |
| contents: read # Required for actions/checkout | |
| id-token: write # IMPORTANT: this permission is mandatory for trusted publishing | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install build twine | |
| - name: Build Python package | |
| run: python -m build | |
| - name: Check package | |
| run: twine check dist/* | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| verbose: true | |
| # Update Homebrew formula (only stable releases from public repo) | |
| update-homebrew: | |
| name: Update Homebrew Formula | |
| runs-on: ubuntu-latest | |
| needs: [build-and-test, build-and-validate-macos-intel, build-and-validate-macos-arm, integration-tests, release-validation, create-release, publish-pypi] | |
| if: github.ref_type == 'tag' && needs.create-release.outputs.is_private_repo != 'true' && needs.create-release.outputs.is_prerelease != 'true' | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Extract SHA256 checksums from GitHub release | |
| id: checksums | |
| run: | | |
| # Download the SHA256 checksum files from the GitHub release | |
| RELEASE_TAG="${{ github.ref_name }}" | |
| echo "Downloading checksums for release $RELEASE_TAG" | |
| # Download checksum files directly from the release | |
| curl -L -o apm-darwin-arm64.tar.gz.sha256 \ | |
| "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-darwin-arm64.tar.gz.sha256" | |
| curl -L -o apm-darwin-x86_64.tar.gz.sha256 \ | |
| "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-darwin-x86_64.tar.gz.sha256" | |
| curl -L -o apm-linux-x86_64.tar.gz.sha256 \ | |
| "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-linux-x86_64.tar.gz.sha256" | |
| curl -L -o apm-linux-arm64.tar.gz.sha256 \ | |
| "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-linux-arm64.tar.gz.sha256" | |
| # Extract SHA256 checksums | |
| DARWIN_ARM64_SHA=$(cat apm-darwin-arm64.tar.gz.sha256 | cut -d' ' -f1) | |
| DARWIN_X86_64_SHA=$(cat apm-darwin-x86_64.tar.gz.sha256 | cut -d' ' -f1) | |
| LINUX_X86_64_SHA=$(cat apm-linux-x86_64.tar.gz.sha256 | cut -d' ' -f1) | |
| LINUX_ARM64_SHA=$(cat apm-linux-arm64.tar.gz.sha256 | cut -d' ' -f1) | |
| echo "darwin-arm64-sha=$DARWIN_ARM64_SHA" >> $GITHUB_OUTPUT | |
| echo "darwin-x86_64-sha=$DARWIN_X86_64_SHA" >> $GITHUB_OUTPUT | |
| echo "linux-x86_64-sha=$LINUX_X86_64_SHA" >> $GITHUB_OUTPUT | |
| echo "linux-arm64-sha=$LINUX_ARM64_SHA" >> $GITHUB_OUTPUT | |
| echo "Darwin ARM64 SHA: $DARWIN_ARM64_SHA" | |
| echo "Darwin x86_64 SHA: $DARWIN_X86_64_SHA" | |
| echo "Linux x86_64 SHA: $LINUX_X86_64_SHA" | |
| echo "Linux ARM64 SHA: $LINUX_ARM64_SHA" | |
| - name: Trigger Homebrew tap repository update | |
| uses: peter-evans/repository-dispatch@v3 | |
| with: | |
| token: ${{ secrets.GH_PKG_PAT }} | |
| repository: microsoft/homebrew-apm | |
| event-type: formula-update | |
| client-payload: | | |
| { | |
| "release": { | |
| "version": "${{ github.ref_name }}", | |
| "tag": "${{ github.ref_name }}", | |
| "repository": "${{ github.repository }}" | |
| }, | |
| "checksums": { | |
| "darwin_arm64": "${{ steps.checksums.outputs.darwin-arm64-sha }}", | |
| "darwin_x86_64": "${{ steps.checksums.outputs.darwin-x86_64-sha }}", | |
| "linux_x86_64": "${{ steps.checksums.outputs.linux-x86_64-sha }}", | |
| "linux_arm64": "${{ steps.checksums.outputs.linux-arm64-sha }}" | |
| } | |
| } | |
| # Update Scoop bucket (only stable releases from public repo) | |
| update-scoop: | |
| name: Update Scoop Bucket | |
| runs-on: ubuntu-latest | |
| needs: [build-and-test, build-and-validate-macos-intel, build-and-validate-macos-arm, integration-tests, release-validation, create-release, publish-pypi] | |
| # TODO: Enable once downstream repository and secrets are configured (see #88) | |
| if: false && github.ref_type == 'tag' && needs.create-release.outputs.is_private_repo != 'true' && needs.create-release.outputs.is_prerelease != 'true' | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Extract Windows checksum from GitHub release | |
| id: checksums | |
| run: | | |
| RELEASE_TAG="${{ github.ref_name }}" | |
| curl -L -o apm-windows-x86_64.zip.sha256 \ | |
| "https://github.com/${{ github.repository }}/releases/download/$RELEASE_TAG/apm-windows-x86_64.zip.sha256" | |
| WINDOWS_X86_64_SHA=$(cat apm-windows-x86_64.zip.sha256 | cut -d' ' -f1) | |
| echo "windows-x86_64-sha=$WINDOWS_X86_64_SHA" >> $GITHUB_OUTPUT | |
| echo "Windows x86_64 SHA: $WINDOWS_X86_64_SHA" | |
| - name: Trigger Scoop bucket repository update | |
| uses: peter-evans/repository-dispatch@v3 | |
| with: | |
| token: ${{ secrets.GH_PKG_PAT }} | |
| repository: microsoft/scoop-apm | |
| event-type: bucket-update | |
| client-payload: | | |
| { | |
| "release": { | |
| "version": "${{ github.ref_name }}", | |
| "tag": "${{ github.ref_name }}", | |
| "repository": "${{ github.repository }}" | |
| }, | |
| "checksums": { | |
| "windows_x86_64": "${{ steps.checksums.outputs.windows-x86_64-sha }}" | |
| } | |
| } |