Create fleetctl pkg asset every release (#35089)
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
name: Build fleetctl macOS package
|
||||
|
||||
# This workflow builds a signed and notarized macOS .pkg installer for fleetctl
|
||||
# for manual testing purposes only.
|
||||
#
|
||||
# NOTE: For production releases, the goreleaser workflow (.github/workflows/goreleaser-fleet.yaml)
|
||||
# handles building and uploading the fleetctl package automatically when a fleet-* tag is pushed.
|
||||
# This workflow is kept for manual testing only.
|
||||
#
|
||||
# TESTING:
|
||||
# To test the package build process:
|
||||
# 1. Go to Actions → Build fleetctl macOS package → Run workflow
|
||||
# 2. Select your branch (e.g., main or feature branch)
|
||||
# 3. Test mode defaults to true (recommended) - package will be built and uploaded as an artifact
|
||||
# 4. To test release upload, set test_mode to false (use with caution)
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Manual trigger for testing only
|
||||
inputs:
|
||||
test_mode:
|
||||
description: "Test mode - will skip release upload if enabled (recommended: true)"
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
# fail-fast using bash -eo pipefail. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
|
||||
shell: bash
|
||||
|
||||
permissions:
|
||||
contents: write # Needed to upload release assets
|
||||
id-token: write # Needed for attestations
|
||||
attestations: write # Needed to create build provenance attestations
|
||||
|
||||
jobs:
|
||||
build-fleetctl-pkg:
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Extract version
|
||||
id: extract_version
|
||||
run: |
|
||||
REF_NAME="${{ github.ref_name }}"
|
||||
|
||||
# Check if running from a tag (for testing tag-based workflows)
|
||||
if [[ "${{ github.ref }}" == refs/tags/* ]] && [[ "$REF_NAME" == fleet-* ]]; then
|
||||
# Extract version from tag (e.g., fleet-v4.10.0 -> 4.10.0)
|
||||
VERSION="${REF_NAME#fleet-v}"
|
||||
TAG_NAME="$REF_NAME"
|
||||
else
|
||||
# For branch-based manual triggers, use a test version
|
||||
VERSION="test-$(date +%Y%m%d-%H%M%S)"
|
||||
TAG_NAME="fleet-${VERSION}"
|
||||
fi
|
||||
|
||||
# Determine test mode based on input (defaults to true for safety)
|
||||
if [ "${{ github.event.inputs.test_mode }}" = "false" ]; then
|
||||
IS_TEST_MODE="false"
|
||||
else
|
||||
# Default to test mode (true) for safety
|
||||
IS_TEST_MODE="true"
|
||||
fi
|
||||
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
|
||||
echo "is_test_mode=$IS_TEST_MODE" >> $GITHUB_OUTPUT
|
||||
echo "Fleet version: $VERSION"
|
||||
if [ "$IS_TEST_MODE" = "true" ]; then
|
||||
echo "⚠️ TEST MODE: Package will be built but NOT uploaded to release"
|
||||
else
|
||||
echo "⚠️ PRODUCTION MODE: Package will be uploaded to release $TAG_NAME"
|
||||
fi
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
|
||||
with:
|
||||
node-version-file: package.json
|
||||
check-latest: true
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
|
||||
- name: Install dependencies
|
||||
run: make deps
|
||||
|
||||
- name: Generate code
|
||||
run: make generate-go
|
||||
|
||||
- name: Build fleetctl binary
|
||||
run: |
|
||||
VERSION="${{ steps.extract_version.outputs.version }}"
|
||||
|
||||
# Extract branch or tag name from ref
|
||||
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||
BRANCH_NAME="${{ steps.extract_version.outputs.tag_name }}"
|
||||
else
|
||||
BRANCH_NAME="${GITHUB_REF#refs/heads/}"
|
||||
fi
|
||||
|
||||
# Set up version ldflags
|
||||
LDFLAGS="-X github.com/fleetdm/fleet/v4/server/version.appName=fleetctl \
|
||||
-X github.com/fleetdm/fleet/v4/server/version.version=${VERSION} \
|
||||
-X github.com/fleetdm/fleet/v4/server/version.branch=${BRANCH_NAME} \
|
||||
-X github.com/fleetdm/fleet/v4/server/version.revision=${GITHUB_SHA} \
|
||||
-X github.com/fleetdm/fleet/v4/server/version.buildDate=$(date -u +%Y-%m-%d) \
|
||||
-X github.com/fleetdm/fleet/v4/server/version.buildUser=github-actions"
|
||||
|
||||
# Build for amd64
|
||||
echo "Building fleetctl for darwin/amd64..."
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build \
|
||||
-trimpath \
|
||||
-ldflags "$LDFLAGS" \
|
||||
-o fleetctl_amd64 \
|
||||
./cmd/fleetctl
|
||||
|
||||
# Build for arm64
|
||||
echo "Building fleetctl for darwin/arm64..."
|
||||
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build \
|
||||
-trimpath \
|
||||
-ldflags "$LDFLAGS" \
|
||||
-o fleetctl_arm64 \
|
||||
./cmd/fleetctl
|
||||
|
||||
# Create universal binary using lipo
|
||||
echo "Creating universal binary..."
|
||||
lipo -create fleetctl_amd64 fleetctl_arm64 -output fleetctl
|
||||
chmod +x fleetctl
|
||||
|
||||
# Clean up architecture-specific binaries
|
||||
rm -f fleetctl_amd64 fleetctl_arm64
|
||||
|
||||
# Verify we have the binary
|
||||
if [ ! -f fleetctl ]; then
|
||||
echo "Error: fleetctl binary not found after build"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify binary works and show version
|
||||
./fleetctl --version
|
||||
|
||||
- name: Import application signing keys (for binary)
|
||||
id: import_app_cert
|
||||
env:
|
||||
APPLE_APPLICATION_CERTIFICATE: ${{ secrets.APPLE_APPLICATION_CERTIFICATE }}
|
||||
APPLE_APPLICATION_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APPLICATION_CERTIFICATE_PASSWORD }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
run: |
|
||||
echo "$APPLE_APPLICATION_CERTIFICATE" | base64 --decode > app_certificate.p12
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain || true
|
||||
security default-keychain -s build.keychain
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
|
||||
security import app_certificate.p12 -k build.keychain -P "$APPLE_APPLICATION_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
|
||||
security find-identity -vv
|
||||
rm app_certificate.p12
|
||||
|
||||
# Extract the signing identity SHA1 from the imported certificate
|
||||
IDENTITY=$(security find-identity -v build.keychain | grep "Developer ID Application" | head -1 | awk '{print $2}')
|
||||
if [[ -z "$IDENTITY" ]]; then
|
||||
echo "Error: No Developer ID Application identity found in keychain"
|
||||
exit 1
|
||||
fi
|
||||
echo "codesign_identity=$IDENTITY" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Sign fleetctl binary
|
||||
run: |
|
||||
# Sign the binary with Developer ID Application certificate
|
||||
codesign --sign "${{ steps.import_app_cert.outputs.codesign_identity }}" \
|
||||
--options runtime \
|
||||
--timestamp \
|
||||
--force \
|
||||
--verbose \
|
||||
fleetctl
|
||||
|
||||
# Verify the signature
|
||||
codesign --verify --verbose fleetctl
|
||||
codesign --display --verbose fleetctl
|
||||
|
||||
- name: Build, sign, and notarize .pkg
|
||||
env:
|
||||
APPLE_INSTALLER_CERTIFICATE: ${{ secrets.APPLE_INSTALLER_CERTIFICATE }}
|
||||
APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
|
||||
APPLE_USERNAME: ${{ secrets.APPLE_USERNAME }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
SKIP_UPLOAD: ${{ steps.extract_version.outputs.is_test_mode }}
|
||||
run: |
|
||||
chmod +x tools/build-fleetctl-pkg/main.sh
|
||||
./tools/build-fleetctl-pkg/main.sh ./fleetctl "${{ steps.extract_version.outputs.version }}"
|
||||
|
||||
- name: Upload package artifact (test mode only)
|
||||
if: steps.extract_version.outputs.is_test_mode == 'true'
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: fleetctl-test-package
|
||||
path: dist/fleetctl_v${{ steps.extract_version.outputs.version }}_mac.pkg
|
||||
retention-days: 7
|
||||
|
||||
- name: Attest package
|
||||
uses: actions/attest-build-provenance@619dbb2e03e0189af0c55118e7d3c5e129e99726 # v2.0
|
||||
with:
|
||||
subject-path: dist/fleetctl_v${{ steps.extract_version.outputs.version }}_mac.pkg
|
||||
push-to-registry: false
|
||||
@@ -23,6 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-22.04-4-cores
|
||||
environment: Docker Hub
|
||||
outputs:
|
||||
binary_uploaded: ${{ steps.check_binary.outputs.exists }}
|
||||
windows_msi_arches: ${{ steps.check_windows_binaries.outputs.arches }}
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -159,6 +160,24 @@ jobs:
|
||||
docker push quay.io/fleetdm/fleet:${TAG}
|
||||
done
|
||||
|
||||
- name: Check if signed binary exists
|
||||
id: check_binary
|
||||
continue-on-error: true
|
||||
run: |
|
||||
if [[ -f "dist/fleetctl_darwin_all/fleetctl" ]]; then
|
||||
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Upload signed fleetctl binary for .pkg creation
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
if: steps.check_binary.outputs.exists == 'true'
|
||||
with:
|
||||
name: fleetctl-signed-macos
|
||||
path: dist/fleetctl_darwin_all/fleetctl
|
||||
retention-days: 1
|
||||
|
||||
- name: Check if Windows fleetctl binaries exist
|
||||
id: check_windows_binaries
|
||||
continue-on-error: true
|
||||
@@ -193,6 +212,68 @@ jobs:
|
||||
path: ${{ steps.check_windows_binaries.outputs.windows_arm64_path }}
|
||||
retention-days: 1
|
||||
|
||||
build-fleetctl-pkg:
|
||||
runs-on: macos-latest
|
||||
needs: goreleaser
|
||||
if: needs.goreleaser.outputs.binary_uploaded == 'true'
|
||||
timeout-minutes: 120
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
|
||||
with:
|
||||
egress-policy: audit
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download signed fleetctl binary
|
||||
uses: actions/download-artifact@5e317d1137c093c30a278992a91e9db4e3c1f039 # v4.1.8
|
||||
with:
|
||||
name: fleetctl-signed-macos
|
||||
path: dist/fleetctl_darwin_all
|
||||
|
||||
- name: Verify binary exists
|
||||
run: |
|
||||
if [[ ! -f "dist/fleetctl_darwin_all/fleetctl" ]]; then
|
||||
echo "Error: Signed fleetctl binary not found"
|
||||
exit 1
|
||||
fi
|
||||
# The download-artifact does not preserve the execute bit,
|
||||
# so set it here so execution doesn't fail.
|
||||
chmod +x dist/fleetctl_darwin_all/fleetctl
|
||||
echo "Binary found, verifying signature..."
|
||||
codesign --verify --verbose dist/fleetctl_darwin_all/fleetctl || exit 1
|
||||
./dist/fleetctl_darwin_all/fleetctl --version
|
||||
|
||||
- name: Build and upload macOS .pkg
|
||||
env:
|
||||
APPLE_INSTALLER_CERTIFICATE: ${{ secrets.APPLE_INSTALLER_CERTIFICATE }}
|
||||
APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
|
||||
APPLE_USERNAME: ${{ secrets.APPLE_USERNAME }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
# Extract version from tag (e.g., fleet-v4.10.0 -> 4.10.0)
|
||||
VERSION="${GITHUB_REF#refs/tags/fleet-v}"
|
||||
chmod +x tools/build-fleetctl-pkg/main.sh
|
||||
./tools/build-fleetctl-pkg/main.sh dist/fleetctl_darwin_all/fleetctl "$VERSION"
|
||||
|
||||
- name: Attest package
|
||||
continue-on-error: true
|
||||
uses: actions/attest-build-provenance@619dbb2e03e0189af0c55118e7d3c5e129e99726 # v2.0
|
||||
with:
|
||||
subject-path: dist/fleetctl_v*_mac.pkg
|
||||
|
||||
build-fleetctl-msi:
|
||||
runs-on: windows-2022
|
||||
needs: goreleaser
|
||||
@@ -290,14 +371,16 @@ jobs:
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
with:
|
||||
name: fleetctl-msi-${{ matrix.arch }}
|
||||
path: dist/fleetctl_v${{ steps.version.outputs.version }}_windows_${{ matrix.arch }}.msi
|
||||
path: dist/fleetctl_v${{ steps.version.outputs.version }}_windows_${{
|
||||
matrix.arch }}.msi
|
||||
retention-days: 1
|
||||
|
||||
- name: Attest MSI
|
||||
continue-on-error: true
|
||||
uses: actions/attest-build-provenance@619dbb2e03e0189af0c55118e7d3c5e129e99726 # v2.0
|
||||
with:
|
||||
subject-path: dist/fleetctl_v${{ steps.version.outputs.version }}_windows_${{ matrix.arch }}.msi
|
||||
subject-path: dist/fleetctl_v${{ steps.version.outputs.version }}_windows_${{
|
||||
matrix.arch }}.msi
|
||||
|
||||
upload-fleetctl-msi:
|
||||
needs: build-fleetctl-msi
|
||||
|
||||
Reference in New Issue
Block a user