Skip to content

chore: simplify README and wire release/GCS publishing for both binaries #5

chore: simplify README and wire release/GCS publishing for both binaries

chore: simplify README and wire release/GCS publishing for both binaries #5

name: Build migrate_agent
on:
push:
branches: [main]
paths:
- 'migrate_agent/**'
- '.github/workflows/build-migrate-agent.yml'
- '.github/workflows/reusable-sign-agent.yml'
workflow_dispatch:
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, picked up by the GCS upload 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 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
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
# =====================================================================
# 3. Sign Windows binaries (jsign + GCP KMS)
# =====================================================================
sign_windows:
name: Sign Windows binaries
needs: merge_windows_unsigned
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: 1
binaries: |
migrate_agent_windows_amd64.exe
migrate_agent_windows_arm64.exe
secrets: inherit
# =====================================================================
# 4. Sign + notarize macOS binary
# =====================================================================
sign_macos:
name: Sign macOS binary
needs: build
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: 1
binaries: |
migrate_agent_darwin_arm64
secrets: inherit
# =====================================================================
# 5. Upload all final binaries to GCS
# Bucket layout consumed by migration-tool/internal/agentmanager:
# gs://utmstack-updates/migration-tool-v10-to-v11/<filename>
# =====================================================================
upload_to_gcs:
name: Upload binaries to GCS
needs: [build, sign_windows, sign_macos]
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write
steps:
- name: Download Linux amd64
uses: actions/download-artifact@v4
with:
name: migrate_agent-linux-amd64-intermediate
path: ./out
- name: Download Linux arm64
uses: actions/download-artifact@v4
with:
name: migrate_agent-linux-arm64-intermediate
path: ./out
- name: Download signed Windows binaries
uses: actions/download-artifact@v4
with:
name: migrate_agent_windows
path: ./out
- name: Download signed macOS binary
uses: actions/download-artifact@v4
with:
name: migrate_agent_darwin_arm64
path: ./out
- name: List binaries to upload
run: ls -lh ./out
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCS_UPLOADER_SA_KEY }}
- name: Upload to gs://utmstack-updates/migration-tool-v10-to-v11
uses: google-github-actions/upload-cloud-storage@v2
with:
path: ./out
destination: utmstack-updates/migration-tool-v10-to-v11
parent: false
process_gcloudignore: false
headers: |
cache-control: no-cache, max-age=0
# =====================================================================
# 6. Clean up intermediate artifacts so they don't clutter
# the run's artifact list. The signed artifacts (migrate_agent_windows,
# migrate_agent_darwin_arm64) are kept short-lived for debugging.
# =====================================================================
cleanup_intermediate:
name: Clean up intermediate artifacts
needs: [upload_to_gcs]
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"