mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
344 lines
14 KiB
YAML
344 lines
14 KiB
YAML
name: goreleaser
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "fleet-*"
|
|
|
|
# This allows a subsequently queued workflow run to interrupt previous runs
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id}}
|
|
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: read
|
|
|
|
jobs:
|
|
goreleaser:
|
|
runs-on: ubuntu-22.04-4-cores
|
|
environment: Docker Hub
|
|
outputs:
|
|
windows_msi_arches: ${{ steps.check_windows_binaries.outputs.arches }}
|
|
permissions:
|
|
contents: write
|
|
id-token: write
|
|
attestations: write
|
|
packages: write
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
|
with:
|
|
fetch-depth: 0 # Needed for goreleaser
|
|
|
|
- name: Login to Docker Hub
|
|
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
|
|
with:
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
|
|
|
|
- name: Set up Go
|
|
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
|
|
with:
|
|
go-version-file: "go.mod"
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1
|
|
with:
|
|
node-version-file: package.json
|
|
|
|
- name: Install JS Dependencies
|
|
run: make deps-js
|
|
|
|
- name: Install macOS signing + notarization tools
|
|
run: |
|
|
pushd /tmp
|
|
readonly version="0.27.0"
|
|
readonly codesign_package="apple-codesign-${version}-x86_64-unknown-linux-musl.tar.gz"
|
|
curl -O -L "https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F${version}/${codesign_package}"
|
|
curl -O -L "https://github.com/indygreg/apple-platform-rs/releases/download/apple-codesign%2F${version}/${codesign_package}.sha256"
|
|
echo "$(cat $codesign_package.sha256) $codesign_package" | sha256sum --quiet --strict --check -
|
|
tar --extract --strip-components 1 --file "$codesign_package"
|
|
mkdir -p $HOME/.bin
|
|
mv rcodesign $HOME/.bin/
|
|
echo "$HOME/.bin" >> $GITHUB_PATH
|
|
popd
|
|
|
|
- name: Run GoReleaser
|
|
id: goreleaser
|
|
uses: goreleaser/goreleaser-action@90a3faa9d0182683851fbfa97ca1a2cb983bfca3 # v6.2.1
|
|
with:
|
|
distribution: goreleaser-pro
|
|
version: "~> 2"
|
|
args: release --clean -f .goreleaser.yml
|
|
env:
|
|
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
APPLE_APPLICATION_CERTIFICATE: ${{ secrets.APPLE_APPLICATION_CERTIFICATE }}
|
|
APPLE_APPLICATION_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APPLICATION_CERTIFICATE_PASSWORD }}
|
|
APPLE_APP_STORE_CONNECT_KEY: ${{ secrets.APPLE_APP_STORE_CONNECT_KEY }}
|
|
APPLE_APP_STORE_CONNECT_KEY_ID: ${{ secrets.APPLE_APP_STORE_CONNECT_KEY_ID }}
|
|
APPLE_APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APPLE_APP_STORE_CONNECT_ISSUER_ID }}
|
|
|
|
- name: Attest binaries and archives
|
|
uses: actions/attest-build-provenance@619dbb2e03e0189af0c55118e7d3c5e129e99726 # v2.0
|
|
with:
|
|
subject-path: "dist/**"
|
|
|
|
- name: Get tag
|
|
run: |
|
|
echo "TAG=$(git describe --tags | sed -e "s/^fleet-//")" >> $GITHUB_OUTPUT
|
|
id: docker
|
|
|
|
# Get the image digests from the goreleaser artifacts
|
|
# Adapted from https://github.com/goreleaser/goreleaser/issues/4852#issuecomment-2122790132
|
|
- name: Get image digests
|
|
continue-on-error: true
|
|
id: image_digests
|
|
run: |
|
|
digest_fleet=$(cat ./dist/artifacts.json | jq -r 'first(.[]|select(.type == "Published Docker Image" and (.name == "fleetdm/fleet:${{ steps.docker.outputs.tag }}")) | select(. != null)|.extra.Digest)')
|
|
echo "digest_fleet=$digest_fleet" >> "$GITHUB_OUTPUT"
|
|
digest_fleetctl=$(cat ./dist/artifacts.json | jq -r 'first(.[]|select(.type == "Published Docker Image" and (.name == "fleetdm/fleetctl:${{ steps.docker.outputs.tag }}")) | select(. != null)|.extra.Digest)')
|
|
echo "digest_fleetctl=$digest_fleetctl" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Attest Fleet image
|
|
uses: actions/attest-build-provenance@619dbb2e03e0189af0c55118e7d3c5e129e99726 # v2.0
|
|
continue-on-error: true
|
|
with:
|
|
subject-digest: ${{steps.image_digests.outputs.digest_fleet}}
|
|
subject-name: "docker.io/fleetdm/fleet"
|
|
push-to-registry: true
|
|
|
|
- name: Attest FleetCtl image
|
|
uses: actions/attest-build-provenance@619dbb2e03e0189af0c55118e7d3c5e129e99726 # v2.0
|
|
continue-on-error: true
|
|
with:
|
|
subject-digest: ${{steps.image_digests.outputs.digest_fleetctl}}
|
|
subject-name: "docker.io/fleetdm/fleetctl"
|
|
push-to-registry: true
|
|
|
|
- name: Update fleetdm/fleet:latest and fleetdm/fleetctl:latest
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
highest_release=$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/fleetdm/fleet/releases | jq -r '.[].tag_name' | sort -r | head -n 1 | sed -e "s/^fleet-//")
|
|
tag=${{ steps.docker.outputs.tag }}
|
|
if [[ $(printf "$highest_release\n$tag" | sort -r | head -n 1) = "$tag" ]]; then
|
|
docker tag fleetdm/fleet:$tag fleetdm/fleet:latest
|
|
docker push fleetdm/fleet:latest
|
|
docker tag fleetdm/fleetctl:$tag fleetdm/fleetctl:latest
|
|
docker push fleetdm/fleetctl:latest
|
|
else
|
|
echo "Skipping tagging of fleetdm/fleet:latest and fleetdm/fleetctl:latest because existing release $highest_release is higher than $tag"
|
|
fi
|
|
|
|
- name: List tags for push
|
|
run: |
|
|
echo "The following TAGs are to be pushed: ${{ steps.docker.outputs.TAG }}"
|
|
|
|
- name: Login to quay.io
|
|
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
|
|
with:
|
|
registry: quay.io
|
|
username: fleetdm+fleetreleaser
|
|
password: ${{ secrets.QUAY_REGISTRY_PASSWORD }}
|
|
|
|
- name: Tag and push to quay.io
|
|
run: |
|
|
for TAG in ${{ steps.docker.outputs.TAG }}; do
|
|
docker tag fleetdm/fleet:${TAG} quay.io/fleetdm/fleet:${TAG}
|
|
docker push quay.io/fleetdm/fleet:${TAG}
|
|
done
|
|
|
|
- name: Check if Windows fleetctl binaries exist
|
|
id: check_windows_binaries
|
|
continue-on-error: true
|
|
run: |
|
|
# Goreleaser v2 places binaries at dist/<id>_<os>_<arch>*/binary
|
|
ARCHES=()
|
|
for arch in amd64 arm64; do
|
|
EXE=$(find dist -name "fleetctl.exe" -path "*windows*${arch}*" -print -quit 2>/dev/null)
|
|
if [[ -n "$EXE" ]]; then
|
|
echo "Found: $EXE"
|
|
echo "windows_${arch}_path=$EXE" >> "$GITHUB_OUTPUT"
|
|
ARCHES+=("\"$arch\"")
|
|
else
|
|
echo "Warning: No fleetctl.exe found for windows/$arch"
|
|
fi
|
|
done
|
|
echo "arches=[$(IFS=,; echo "${ARCHES[*]}")]" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Upload unsigned Windows fleetctl amd64
|
|
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
|
if: steps.check_windows_binaries.outputs.windows_amd64_path != ''
|
|
with:
|
|
name: fleetctl-unsigned-windows-amd64
|
|
path: ${{ steps.check_windows_binaries.outputs.windows_amd64_path }}
|
|
retention-days: 1
|
|
|
|
- name: Upload unsigned Windows fleetctl arm64
|
|
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
|
if: steps.check_windows_binaries.outputs.windows_arm64_path != ''
|
|
with:
|
|
name: fleetctl-unsigned-windows-arm64
|
|
path: ${{ steps.check_windows_binaries.outputs.windows_arm64_path }}
|
|
retention-days: 1
|
|
|
|
build-fleetctl-msi:
|
|
runs-on: windows-2022
|
|
needs: goreleaser
|
|
if: needs.goreleaser.outputs.windows_msi_arches != '[]'
|
|
timeout-minutes: 60
|
|
strategy:
|
|
matrix:
|
|
arch: ${{ fromJSON(needs.goreleaser.outputs.windows_msi_arches) }}
|
|
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
|
|
|
|
- name: Download unsigned fleetctl binary
|
|
uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.8
|
|
with:
|
|
name: fleetctl-unsigned-windows-${{ matrix.arch }}
|
|
|
|
- name: Verify binary exists
|
|
run: |
|
|
if [[ ! -f "fleetctl.exe" ]]; then
|
|
echo "Error: fleetctl.exe not found after download"
|
|
ls -la
|
|
exit 1
|
|
fi
|
|
echo "Binary found ($(wc -c < fleetctl.exe) bytes)"
|
|
|
|
- name: Extract version from tag
|
|
id: version
|
|
run: |
|
|
TAG_NAME="${{ github.ref_name }}"
|
|
VERSION="${TAG_NAME#fleet-}"
|
|
VERSION="${VERSION#v}"
|
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
echo "Version: $VERSION"
|
|
|
|
- name: Install WiX 3.14.1
|
|
run: |
|
|
curl -fSL -o wix314-binaries.zip \
|
|
https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip
|
|
mkdir -p "$RUNNER_TEMP/wix"
|
|
unzip -q wix314-binaries.zip -d "$RUNNER_TEMP/wix"
|
|
echo "$RUNNER_TEMP/wix" >> $GITHUB_PATH
|
|
|
|
- name: Setup DigiCert KeyLocker
|
|
env:
|
|
DIGICERT_KEYLOCKER_CERTIFICATE: ${{ secrets.DIGICERT_KEYLOCKER_CERTIFICATE }}
|
|
DIGICERT_KEYLOCKER_PASSWORD: ${{ secrets.DIGICERT_KEYLOCKER_PASSWORD }}
|
|
DIGICERT_KEYLOCKER_HOST_URL: ${{ secrets.DIGICERT_KEYLOCKER_HOST_URL }}
|
|
DIGICERT_API_KEY: ${{ secrets.DIGICERT_API_KEY }}
|
|
run: |
|
|
echo "$DIGICERT_KEYLOCKER_CERTIFICATE" | base64 --decode > /d/Certificate_pkcs12.p12
|
|
echo "SM_HOST=$DIGICERT_KEYLOCKER_HOST_URL" >> "$GITHUB_ENV"
|
|
echo "SM_API_KEY=$DIGICERT_API_KEY" >> "$GITHUB_ENV"
|
|
echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV"
|
|
echo "SM_CLIENT_CERT_PASSWORD=$DIGICERT_KEYLOCKER_PASSWORD" >> "$GITHUB_ENV"
|
|
echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH
|
|
echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH
|
|
echo "C:\Program Files\DigiCert\DigiCert Keylocker Tools" >> $GITHUB_PATH
|
|
|
|
- name: Install DigiCert KeyLocker KSP
|
|
run: |
|
|
curl https://one.digicert.com/signingmanager/api-ui/v1/releases/Keylockertools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" --fail-with-body -o Keylockertools-windows-x64.msi
|
|
msiexec /i Keylockertools-windows-x64.msi /quiet /qn
|
|
smksp_registrar.exe list
|
|
smctl.exe keypair ls
|
|
C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
|
|
shell: cmd
|
|
|
|
- name: Sync certificates
|
|
run: |
|
|
smctl windows certsync
|
|
shell: cmd
|
|
|
|
- name: Build and sign MSI
|
|
env:
|
|
DIGICERT_KEYLOCKER_CERTIFICATE_FINGERPRINT: ${{ secrets.DIGICERT_KEYLOCKER_CERTIFICATE_FINGERPRINT }}
|
|
SKIP_UPLOAD: "true"
|
|
run: |
|
|
chmod +x tools/build-fleetctl-msi/main.sh
|
|
./tools/build-fleetctl-msi/main.sh \
|
|
fleetctl.exe \
|
|
"${{ steps.version.outputs.version }}" \
|
|
"${{ matrix.arch }}"
|
|
|
|
- name: Upload signed MSI artifact
|
|
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
|
|
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
|
|
|
|
upload-fleetctl-msi:
|
|
needs: build-fleetctl-msi
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Download signed MSI artifacts
|
|
uses: actions/download-artifact@9c19ed7fe5d278cd354c7dfd5d3b88589c7e2395 # v4.1.8
|
|
with:
|
|
pattern: fleetctl-msi-*
|
|
merge-multiple: true
|
|
path: dist
|
|
|
|
- name: Upload MSIs to release
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
TAG_NAME="${{ github.ref_name }}"
|
|
echo "Uploading MSIs to release $TAG_NAME..."
|
|
|
|
# Wait for release to exist
|
|
MAX_WAIT=300
|
|
ELAPSED=0
|
|
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
|
if gh release view "$TAG_NAME" --repo "$GITHUB_REPOSITORY" &>/dev/null; then
|
|
echo "Release found"
|
|
break
|
|
fi
|
|
echo "Waiting for release... (${ELAPSED}s/${MAX_WAIT}s)"
|
|
sleep 10
|
|
ELAPSED=$((ELAPSED + 10))
|
|
done
|
|
|
|
for msi in dist/*.msi; do
|
|
echo "Uploading $msi..."
|
|
gh release upload "$TAG_NAME" "$msi" --repo "$GITHUB_REPOSITORY" --clobber
|
|
done
|
|
echo "Upload complete"
|