Build migrate_agent #4
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: Build migrate_agent (manual) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| sign: | |
| description: "Sign Windows binaries via GCP KMS and notarize macOS binaries via Apple notarytool." | |
| required: false | |
| type: boolean | |
| default: true | |
| permissions: | |
| contents: read | |
| id-token: write | |
| actions: write | |
| jobs: | |
| # ===================================================================== | |
| # 1. Build all platforms (no signing yet) | |
| # ===================================================================== | |
| build: | |
| name: Build ${{ matrix.goos }}/${{ matrix.goarch }} | |
| runs-on: ubuntu-24.04 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - goos: linux | |
| goarch: amd64 | |
| ext: "" | |
| - goos: linux | |
| goarch: arm64 | |
| ext: "" | |
| - goos: windows | |
| goarch: amd64 | |
| ext: ".exe" | |
| - goos: windows | |
| goarch: arm64 | |
| ext: ".exe" | |
| - goos: darwin | |
| goarch: arm64 | |
| ext: "" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: migrate_agent/go.mod | |
| cache: true | |
| cache-dependency-path: migrate_agent/go.sum | |
| - name: Build binary | |
| working-directory: migrate_agent | |
| env: | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| CGO_ENABLED: 0 | |
| run: | | |
| OUT="migrate_agent_${{ matrix.goos }}_${{ matrix.goarch }}${{ matrix.ext }}" | |
| echo "→ Building $OUT" | |
| go build -trimpath -ldflags="-s -w" -o "$OUT" . | |
| ls -lh "$OUT" | |
| # Linux: intermediate per-arch bundle, merged by the merge_linux job | |
| - name: Stage Linux binary | |
| if: matrix.goos == 'linux' | |
| run: | | |
| mkdir -p staging-linux | |
| cp migrate_agent/migrate_agent_${{ matrix.goos }}_${{ matrix.goarch }}${{ matrix.ext }} staging-linux/ | |
| - name: Upload Linux binary (intermediate) | |
| if: matrix.goos == 'linux' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: migrate_agent-linux-${{ matrix.goarch }}-intermediate | |
| path: staging-linux/ | |
| retention-days: 1 | |
| if-no-files-found: error | |
| # Windows: temporary unsigned bundle, picked up by the signing job | |
| - name: Stage unsigned Windows binary | |
| if: matrix.goos == 'windows' | |
| run: | | |
| mkdir -p staging-windows | |
| cp migrate_agent/migrate_agent_${{ matrix.goos }}_${{ matrix.goarch }}${{ matrix.ext }} staging-windows/ | |
| - name: Upload unsigned Windows binary (intermediate) | |
| if: matrix.goos == 'windows' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: migrate_agent-windows-${{ matrix.goarch }}-unsigned | |
| path: staging-windows/ | |
| retention-days: 1 | |
| if-no-files-found: error | |
| # macOS: temporary unsigned bundle, picked up by the signing job | |
| - name: Stage unsigned macOS binary | |
| if: matrix.goos == 'darwin' | |
| run: | | |
| mkdir -p staging-darwin | |
| cp migrate_agent/migrate_agent_${{ matrix.goos }}_${{ matrix.goarch }}${{ matrix.ext }} staging-darwin/ | |
| - name: Upload unsigned macOS binary (intermediate) | |
| if: matrix.goos == 'darwin' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: migrate_agent-darwin-${{ matrix.goarch }}-unsigned | |
| path: staging-darwin/ | |
| retention-days: 1 | |
| if-no-files-found: error | |
| # ===================================================================== | |
| # 2. Merge Linux binaries into a single final artifact | |
| # (Linux is not signed, so this is the final output) | |
| # ===================================================================== | |
| merge_linux: | |
| name: Merge Linux binaries | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Download amd64 | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: migrate_agent-linux-amd64-intermediate | |
| path: ./merged | |
| - name: Download arm64 | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: migrate_agent-linux-arm64-intermediate | |
| path: ./merged | |
| - name: List contents | |
| run: ls -la ./merged | |
| - name: Upload final Linux bundle | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: migrate_agent_linux | |
| path: ./merged/ | |
| retention-days: 7 | |
| if-no-files-found: error | |
| # ===================================================================== | |
| # 3. Merge Windows unsigned binaries into a single artifact | |
| # (reusable-sign-agent.yml expects ONE artifact with all binaries) | |
| # ===================================================================== | |
| merge_windows_unsigned: | |
| name: Merge unsigned Windows binaries | |
| needs: build | |
| if: ${{ inputs.sign }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Download amd64 | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: migrate_agent-windows-amd64-unsigned | |
| path: ./merged | |
| - name: Download arm64 | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: migrate_agent-windows-arm64-unsigned | |
| path: ./merged | |
| - name: List contents | |
| run: ls -la ./merged | |
| - name: Upload merged unsigned bundle | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: migrate_agent-windows-unsigned | |
| path: ./merged/ | |
| retention-days: 1 | |
| if-no-files-found: error | |
| # ===================================================================== | |
| # 4. Sign Windows binaries (jsign + GCP KMS) | |
| # ===================================================================== | |
| sign_windows: | |
| name: Sign Windows binaries | |
| needs: merge_windows_unsigned | |
| if: ${{ inputs.sign }} | |
| uses: ./.github/workflows/reusable-sign-agent.yml | |
| with: | |
| os: windows | |
| artifact_name: migrate_agent-windows-unsigned | |
| signed_artifact_name: migrate_agent_windows | |
| gcp_project_id: ${{ vars.GCP_PROJECT_PROD }} | |
| kms_location: ${{ vars.KMS_KEYRING_LOCATION }} | |
| kms_keyring: ${{ vars.KMS_KEYRING_NAME }} | |
| kms_key: ${{ vars.KMS_KEY_NAME }} | |
| sign_name: "UTMStack MigrationTool Agent" | |
| sign_url: "https://utmstack.com" | |
| retention_days: 7 | |
| binaries: | | |
| migrate_agent_windows_amd64.exe | |
| migrate_agent_windows_arm64.exe | |
| secrets: inherit | |
| # ===================================================================== | |
| # 5. Sign + notarize macOS binary | |
| # ===================================================================== | |
| sign_macos: | |
| name: Sign macOS binary | |
| needs: build | |
| if: ${{ inputs.sign }} | |
| uses: ./.github/workflows/reusable-sign-agent.yml | |
| with: | |
| os: macos | |
| artifact_name: migrate_agent-darwin-arm64-unsigned | |
| signed_artifact_name: migrate_agent_darwin_arm64 | |
| retention_days: 7 | |
| binaries: | | |
| migrate_agent_darwin_arm64 | |
| secrets: inherit | |
| # ===================================================================== | |
| # 6. Clean up intermediate artifacts so they don't clutter | |
| # the run's artifact list. | |
| # ===================================================================== | |
| cleanup_intermediate: | |
| name: Clean up intermediate artifacts | |
| needs: [merge_linux, sign_windows, sign_macos] | |
| if: ${{ always() }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Delete intermediate artifacts | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| RUN_ID: ${{ github.run_id }} | |
| run: | | |
| set -euo pipefail | |
| TARGETS=( | |
| "migrate_agent-linux-amd64-intermediate" | |
| "migrate_agent-linux-arm64-intermediate" | |
| "migrate_agent-windows-amd64-unsigned" | |
| "migrate_agent-windows-arm64-unsigned" | |
| "migrate_agent-darwin-arm64-unsigned" | |
| "migrate_agent-windows-unsigned" | |
| ) | |
| echo "→ Listing artifacts for run $RUN_ID" | |
| artifacts_json=$(gh api \ | |
| "repos/${REPO}/actions/runs/${RUN_ID}/artifacts" \ | |
| --paginate) | |
| for name in "${TARGETS[@]}"; do | |
| ids=$(echo "$artifacts_json" | jq -r \ | |
| --arg name "$name" \ | |
| '.artifacts[] | select(.name == $name) | .id') | |
| if [ -z "$ids" ]; then | |
| echo "· $name: not found, skipping" | |
| continue | |
| fi | |
| for id in $ids; do | |
| echo "→ Deleting $name (id=$id)" | |
| gh api -X DELETE "repos/${REPO}/actions/artifacts/${id}" \ | |
| && echo " ✓ deleted" \ | |
| || echo " ✗ failed (continuing)" | |
| done | |
| done | |
| echo "✓ Cleanup done" |