Update create release. #3644
Workflow file for this run
This file contains 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
# Build and test on each commit. Create a release on tagged commits. | |
# | |
# Binaries on each platform are stripped. This removes debug symbols. | |
name: Build | |
on: [push] | |
jobs: | |
build-all: | |
name: ${{ matrix.os-name }}-build | |
runs-on: ${{ matrix.os }} | |
container: ${{ matrix.container }} | |
env: | |
# TODO: Use either this or the matrix value | |
GHC_VERSION: '9.8.2' | |
CARGO_TARGET: ${{ matrix.cargo-target }} | |
defaults: | |
run: | |
shell: bash | |
strategy: | |
matrix: | |
os: [ 'LinuxARM', 'windows-latest', 'ubuntu-latest', 'macos-12', 'macos-latest'] | |
include: | |
- os: LinuxARM | |
os-name: Linux-arm | |
project-file: cabal.project.ci.linux | |
ghc: '9.8.2' | |
- os: ubuntu-latest | |
os-name: Linux | |
container: fossa/haskell-static-alpine:ghc-9.8.2 | |
project-file: cabal.project.ci.linux | |
ghc: '9.8.2' | |
# macos-latest pointed at macos-12 this before it was changed to ARM. | |
- os: macos-12 | |
os-name: macOS-intel | |
project-file: cabal.project.ci.macos | |
ghc: '9.8.2' | |
- os: windows-latest | |
os-name: Windows | |
project-file: cabal.project.ci.windows | |
ghc: '9.8.2' | |
- os: macos-latest | |
os-name: macOS-arm64 | |
project-file: cabal.project.ci.macos | |
ghc: '9.8.2' | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
lfs: true | |
fetch-depth: 2 | |
- name: Install MacOS binary dependencies | |
if: ${{ contains(matrix.os, 'macos') }} | |
run: | | |
brew install jq | |
# Set up Haskell. | |
- uses: haskell-actions/setup@v2 | |
id: setup-haskell | |
name: Setup ghc/cabal (non-alpine) | |
if: ${{ !contains(matrix.os-name, 'Linux') }} | |
with: | |
ghc-version: ${{ matrix.ghc }} | |
cabal-version: '3.10.3.0' | |
# Set up Rust, this is mainly used for rust-cache. | |
# This action installs the 'minimal' profile. | |
# Even on Linux ARM this is necessary because rust-cache uses it. | |
- uses: dtolnay/rust-toolchain@stable | |
- uses: Swatinem/rust-cache@v2 | |
with: | |
# This additional directory is because the home directory inside containers | |
# is different than the one outside of it. | |
cache-directories: ${{ runner.temp }}/_github_home/.cargo | |
- name: Debugging information | |
run: | | |
ghc --version || echo "no ghc" | |
cabal --version || echo "no cabal" | |
ghcup --version || echo "no ghcup" | |
# Linux builds are run in Alpine, which builds them statically; | |
# using jemalloc reduces the performance impact of this | |
# over the default libc allocator (which performs very poorly in static builds). | |
- name: Build Rust dependencies (Linux) | |
if: ${{ matrix.os-name == 'Linux' }} | |
run: | | |
cargo build --features jemalloc --release | |
# Non-Linux environments generally don't need `jemalloc` | |
# and in particular Windows doesn't support it. | |
- name: Build Rust dependencies (non-Linux) | |
if: ${{ ! contains(matrix.os-name, 'linux') }} | |
run: cargo build --release | |
# Run tests in release mode to reduce the need for rebuilds. | |
# - name: Test Rust dependencies | |
# run: cargo nextest run --release | |
- name: Ensure git ownership check does not lead to compiler error | |
run: git config --global --add safe.directory "$GITHUB_WORKSPACE" | |
- name: Check git status and collect information | |
# https://github.com/actions/checkout/issues/760#issuecomment-1099519159 | |
run: | | |
git status --porcelain | |
echo "parent_commit=$(git rev-parse HEAD^)" >> $GITHUB_ENV | |
# Compute cache key and save to a temporary file. | |
# | |
# We compute the cache key based on the solved install plan instead of just | |
# hashing the `.cabal` file, since there are many kinds of changes that will | |
# cause `.cabal` to change (e.g. adding new source modules). | |
# | |
- name: Compute cache key (not ARM Linux) | |
if: ${{ matrix.os != 'LinuxARM' }} | |
id: compute-cache-key | |
run: ./.github/workflows/scripts/compute_cache_key.sh ${{ runner.os }} ${{ matrix.project-file }} | |
- name: Compute Cache Key (Linux Arm) | |
if: ${{ matrix.os == 'LinuxARM' }} | |
id: compute-cache-key-arm | |
uses: docker://fossa/haskell-static-alpine:ghc-9.8.2 | |
with: | |
args: ./.github/workflows/scripts/compute_cache_key.sh ${{ runner.os }} ${{ matrix.project-file }} | |
# The home directory inside a github container run during a step is different than one run outside of it. | |
# This is why there is special logic for 'LinuxARM'. | |
# Its builds run inside a container but are cached by an action outside of it.. | |
- uses: actions/cache@v4 | |
name: Cache cabal store | |
with: | |
path: ${{ steps.setup-haskell.outputs.cabal-store || ( matrix.os == 'LinuxARM' && format('{0}/_github_home/.local/state/cabal', runner.temp) || '~/.local/state/cabal') }} | |
key: ${{ matrix.os-name }}-${{ matrix.ghc }}-cabal-cache-${{ steps.compute-cache-key.outputs.cabal-cache-key || steps.compute-cache-key-arm.outputs.cabal-cache-key }} | |
restore-keys: | | |
${{ matrix.os-name }}-${{ matrix.ghc }}-cabal-cache- | |
${{ matrix.os-name }}-${{ matrix.ghc }}- | |
- uses: actions/cache@v4 | |
name: Cache dist-newstyle | |
with: | |
path: ${{ github.workspace }}/dist-newstyle | |
key: ${{ matrix.os-name }}-${{ env.GHC_VERSION }}-dist-newstyle-${{ github.sha }} | |
restore-keys: | | |
${{ matrix.os-name }}-${{ env.GHC_VERSION }}-dist-newstyle-${{ env.parent_commit }} | |
${{ matrix.os-name }}-${{ env.GHC_VERSION }}-dist-newstyle- | |
${{ matrix.os-name }}-${{ env.GHC_VERSION }}- | |
- name: Update vendored binaries | |
run: | | |
mkdir vendor-bins | |
./vendor_download.sh | |
env: | |
GITHUB_TOKEN: ${{ secrets.BASIS_ACCESS_TOKEN }} | |
- name: Build and Unit Test (Linux ARM) | |
if: ${{ matrix.os == 'LinuxARM' }} | |
uses: docker://fossa/haskell-static-alpine:ghc-9.8.2 | |
with: | |
args: ./.github/workflows/scripts/build-arm.sh ${{ runner.os }} ${{ matrix.project-file }} | |
- name: Build and Unit Test | |
if: ${{ matrix.os != 'LinuxARM' }} | |
run: ./.github/workflows/scripts/build.sh ${{ runner.os }} ${{ matrix.project-file }} | |
# TODO: Got a permissions error, I'm guessing that the directory inside the image has bad perms outside of it. | |
# - name: Validate diagnose commands run on the platform | |
# run: | | |
# cargo run --release --bin diagnose -- walk --trace-spans none --trace-level info | |
# Save artifacts. | |
- name: Find and move binaries (Windows) | |
if: ${{ contains(matrix.os, 'windows') }} | |
run: | | |
mkdir release | |
find . -type f -path '*/fossa/fossa.exe' -exec cp {} release \; | |
./release/fossa.exe --version | |
cp target/release/diagnose.exe release | |
cp target/release/millhone.exe release | |
- name: Find and move binaries (non-Windows) | |
if: ${{ !contains(matrix.os, 'windows') }} | |
run: | | |
mkdir release | |
find . -type f -path '*/fossa/fossa' -exec cp {} release \; | |
./release/fossa --version | |
cp target/release/diagnose release | |
cp target/release/millhone release | |
- name: Strip binaries | |
run: | | |
strip release/* | |
- name: Sign and Notarize Binaries (Mac OS) | |
if: ${{ contains(matrix.os, 'macos') && startsWith(github.ref, 'refs/tags/v') }} | |
env: | |
MACOS_BUILD_CERT_BASE64: ${{ secrets.MACOS_BUILD_CERT_BASE64 }} | |
MACOS_BUILD_CERT_P12_PASSWORD: ${{ secrets.MACOS_BUILD_CERT_P12_PASSWORD }} | |
MACOS_KEYCHAIN_PASSWORD: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }} | |
APPLE_NOTARIZATION_DEV_PASS: ${{ secrets.APPLE_NOTARIZATION_DEV_PASS }} | |
APPLE_NOTARIZATION_DEV_ID: ${{ secrets.APPLE_NOTARIZATION_DEV_ID }} | |
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
OS_NAME: ${{ matrix.os-name }} | |
run: | | |
# create variables | |
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 | |
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db | |
# import certificate and provisioning profile from secrets | |
echo -n "$MACOS_BUILD_CERT_BASE64" | base64 --decode -o $CERTIFICATE_PATH | |
# create temporary keychain | |
security create-keychain -p "$MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH | |
security unlock-keychain -p "$MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | |
# import certificate to keychain | |
security import $CERTIFICATE_PATH -P "$MACOS_BUILD_CERT_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | |
security list-keychain -d user -s $KEYCHAIN_PATH | |
chmod +x release/* | |
# '--options runtime' enables the hardened runtime: https://developer.apple.com/documentation/security/hardened_runtime | |
# On Apple Silicon there doesn't seem to be a default liblzma, and the one installed via homebrew is rejected. | |
# The entitlement line will relax that check. | |
# The hardened runtime is required for notarization. | |
if [ "$OS_NAME" = "macOS-arm64" ] ; then | |
codesign --entitlements .github/entitlements.plist --options runtime -s 'FOSSA, Inc.' release/fossa | |
else | |
# Intel does not need the entitlement to run liblzma, which is included in the base system. | |
codesign --options runtime -s 'FOSSA, Inc.' release/fossa | |
fi | |
codesign --options runtime -s 'FOSSA, Inc.' release/diagnose | |
codesign --options runtime -s 'FOSSA, Inc.' release/millhone | |
# Perform notarization | |
zip -rj notarization-archive.zip release | |
NOTARY_RESULTS=$(xcrun notarytool submit notarization-archive.zip --apple-id "$APPLE_NOTARIZATION_DEV_ID" --password "$APPLE_NOTARIZATION_DEV_PASS" --team-id "$APPLE_TEAM_ID" --wait) | |
echo "$NOTARY_RESULTS" | |
rm notarization-archive.zip | |
# The notarization tool doesn't set $?, so examine the output. | |
if ! echo "$NOTARY_RESULTS" | grep -q "status: Accepted"; then | |
exit 1 | |
fi | |
- uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ matrix.os-name }}-binaries | |
path: release | |
create-release: | |
name: create-release | |
runs-on: ubuntu-latest | |
needs: ['build-all'] | |
permissions: | |
id-token: write | |
contents: write | |
steps: | |
- uses: actions/download-artifact@v4 | |
# Sets VERSION from git's tag or sha. | |
# refer to: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-of-setting-an-output-parameter | |
- name: Get version | |
id: get-version | |
run: | | |
case $GITHUB_REF in | |
refs/tags/v*) | |
# This strips the 'v' prefix from the tag. | |
echo "VERSION=${GITHUB_REF/refs\/tags\/v/}" >> "$GITHUB_OUTPUT" | |
;; | |
*) | |
echo "VERSION=${GITHUB_SHA}" >> "$GITHUB_OUTPUT" | |
;; | |
esac | |
- name: Check that version info was embedded correctly | |
if: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
run: | | |
chmod +x Linux-binaries/fossa | |
echo $GITHUB_REF_NAME | |
echo $GITHUB_REF_TYPE | |
echo $GITHUB_SHA | |
echo ${GITHUB_SHA:0:12} | |
VERSION=$(echo $(Linux-binaries/fossa --version)) | |
EXPECTED="fossa-cli version ${{ steps.get-version.outputs.VERSION }} (revision ${GITHUB_SHA:0:12} compiled with ghc-9.8)" | |
echo "VERSION: $VERSION" | |
echo "EXPECTED: $EXPECTED" | |
[ "$GITHUB_REF_TYPE" = "tag" ] && echo "Ref type OK" | |
[ "$VERSION" = "$EXPECTED" ] && echo "CLI version OK" | |
- name: Install Cosign | |
if: ${{ github.ref_type == 'tag' }} | |
uses: sigstore/[email protected] | |
- name: Sign and Verify Release (Linux) | |
if: ${{ github.ref_type == 'tag' }} | |
run: | | |
cosign version | |
for linux_kind in 'Linux' 'Linux-arm' | |
do | |
cosign sign-blob --yes --bundle "$linux_kind-binaries/fossa.bundle" "$linux_kind-binaries/fossa" | |
cosign sign-blob --yes --bundle "$linux_kind-binaries/diagnose.bundle" "$linux_kind-binaries/diagnose" | |
cosign sign-blob --yes --bundle "$linux_kind-binaries/millhone.bundle" "$linux_kind-binaries/millhone" | |
cosign verify-blob --bundle "$linux_kind-binaries/fossa.bundle" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --certificate-identity "https://github.com/$GITHUB_WORKFLOW_REF" $linux_kind-binaries/fossa" | |
cosign verify-blob --bundle "$linux_kind-binaries/diagnose.bundle" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --certificate-identity "https://github.com/$GITHUB_WORKFLOW_REF" $linux_kind-binaries/diagnose" | |
cosign verify-blob --bundle "$linux_kind-binaries/millhone.bundle" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --certificate-identity "https://github.com/$GITHUB_WORKFLOW_REF" $linux_kind-binaries/millhone" | |
done | |
# - name: Verify Signatures | |
# if: ${{ github.ref_type == 'tag' }} | |
# run: | | |
# cosign verify-blob --bundle "Linux-binaries/fossa.bundle" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --certificate-identity "https://github.com/$GITHUB_WORKFLOW_REF" "Linux-binaries/fossa" | |
# cosign verify-blob --bundle "Linux-binaries/diagnose.bundle" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --certificate-identity "https://github.com/$GITHUB_WORKFLOW_REF" "Linux-binaries/diagnose" | |
# cosign verify-blob --bundle "Linux-binaries/millhone.bundle" --certificate-oidc-issuer "https://token.actions.githubusercontent.com" --certificate-identity "https://github.com/$GITHUB_WORKFLOW_REF" "Linux-binaries/millhone" | |
# This uses names compatible with our install script. | |
# | |
# Originally, CLI >=2.x Linux releases were only packaged as zip files, but | |
# we added tar.gz to improve compatibility. Our install script depends on | |
# the unzip command, which is not installed in most Linux distributions by | |
# default. To avoid breaking compatibility with older install scripts, we | |
# release both formats but default to using tar.gz when installing. | |
- name: Bundle binaries | |
env: | |
LINUX_FOSSA_TAR_PATH: "release/fossa_${{ steps.get-version.outputs.VERSION }}_linux_amd64.tar" | |
LINUX_FOSSA_ZIP_PATH: "release/fossa_${{ steps.get-version.outputs.VERSION }}_linux_amd64.zip" | |
LINUX_DIAGNOSE_TAR_PATH: "release/diagnose_${{ steps.get-version.outputs.VERSION }}_linux_amd64.tar" | |
LINUX_DIAGNOSE_ZIP_PATH: "release/diagnose_${{ steps.get-version.outputs.VERSION }}_linux_amd64.zip" | |
LINUX_MILLHONE_TAR_PATH: "release/millhone_${{ steps.get-version.outputs.VERSION }}_linux_amd64.tar" | |
LINUX_MILLHONE_ZIP_PATH: "release/millhone_${{ steps.get-version.outputs.VERSION }}_linux_amd64.zip" | |
LINUX_ARM_FOSSA_TAR_PATH: "release/fossa_${{ steps.get-version.outputs.VERSION }}_linux_arm64.tar" | |
LINUX_ARM_FOSSA_ZIP_PATH: "release/fossa_${{ steps.get-version.outputs.VERSION }}_linux_arm64.zip" | |
LINUX_ARM_DIAGNOSE_TAR_PATH: "release/diagnose_${{ steps.get-version.outputs.VERSION }}_linux_arm64.tar" | |
LINUX_ARM_DIAGNOSE_ZIP_PATH: "release/diagnose_${{ steps.get-version.outputs.VERSION }}_linux_arm64.zip" | |
LINUX_ARM_MILLHONE_TAR_PATH: "release/millhone_${{ steps.get-version.outputs.VERSION }}_linux_arm64.tar" | |
LINUX_ARM_MILLHONE_ZIP_PATH: "release/millhone_${{ steps.get-version.outputs.VERSION }}_linux_arm64.zip" | |
run: | | |
mkdir release | |
ls -R | |
chmod +x Linux*-binaries/* | |
zip -j "$LINUX_FOSSA_ZIP_PATH" Linux-binaries/fossa | |
zip -j "$LINUX_DIAGNOSE_ZIP_PATH" Linux-binaries/diagnose | |
zip -j "$LINUX_MILLHONE_ZIP_PATH" Linux-binaries/millhone | |
tar --create --verbose --file "$LINUX_FOSSA_TAR_PATH" --directory Linux-binaries fossa | |
tar --create --verbose --file "$LINUX_DIAGNOSE_TAR_PATH" --directory Linux-binaries diagnose | |
tar --create --verbose --file "$LINUX_MILLHONE_TAR_PATH" --directory Linux-binaries millhone | |
zip -j "$LINUX_ARM_FOSSA_ZIP_PATH" Linux-arm-binaries/fossa | |
zip -j "$LINUX_ARM_DIAGNOSE_ZIP_PATH" Linux-arm-binaries/diagnose | |
zip -j "$LINUX_ARM_MILLHONE_ZIP_PATH" Linux-arm-binaries/millhone | |
tar --create --verbose --file "$LINUX_ARM_FOSSA_TAR_PATH" --directory Linux-arm-binaries fossa | |
tar --create --verbose --file "$LINUX_ARM_DIAGNOSE_TAR_PATH" --directory Linux-arm-binaries diagnose | |
tar --create --verbose --file "$LINUX_ARM_MILLHONE_TAR_PATH" --directory Linux-arm-binaries millhone | |
if [ "$GITHUB_REF_TYPE" = "tag" ]; then | |
# TODO: add the arm stuff | |
tar --append --file "$LINUX_FOSSA_TAR_PATH" --directory Linux-binaries fossa.bundle | |
tar --append --file "$LINUX_DIAGNOSE_TAR_PATH" --directory Linux-binaries diagnose.bundle | |
tar --append --file "$LINUX_MILLHONE_TAR_PATH" --directory Linux-binaries millhone.bundle | |
zip -j "$LINUX_FOSSA_ZIP_PATH" Linux-binaries/fossa.bundle | |
zip -j "$LINUX_DIAGNOSE_ZIP_PATH" Linux-binaries/diagnose.bundle | |
zip -j "$LINUX_MILLHONE_ZIP_PATH" Linux-binaries/millhone.bundle | |
fi | |
gzip "$LINUX_FOSSA_TAR_PATH" | |
gzip "$LINUX_DIAGNOSE_TAR_PATH" | |
gzip "$LINUX_MILLHONE_TAR_PATH" | |
gzip "$LINUX_ARM_FOSSA_TAR_PATH" | |
gzip "$LINUX_ARM_DIAGNOSE_TAR_PATH" | |
gzip "$LINUX_ARM_MILLHONE_TAR_PATH" | |
chmod +x macOS-intel-binaries/* | |
zip -j release/fossa_${{ steps.get-version.outputs.VERSION }}_darwin_amd64.zip macOS-intel-binaries/fossa | |
zip -j release/diagnose_${{ steps.get-version.outputs.VERSION }}_darwin_amd64.zip macOS-intel-binaries/diagnose | |
zip -j release/millhone_${{ steps.get-version.outputs.VERSION }}_darwin_amd64.zip macOS-intel-binaries/millhone | |
chmod +x macOS-arm64-binaries/* | |
zip -j release/fossa_${{ steps.get-version.outputs.VERSION }}_darwin_arm64.zip macOS-arm64-binaries/fossa | |
zip -j release/diagnose_${{ steps.get-version.outputs.VERSION }}_darwin_arm64.zip macOS-arm64-binaries/diagnose | |
zip -j release/millhone_${{ steps.get-version.outputs.VERSION }}_darwin_arm64.zip macOS-arm64-binaries/millhone | |
chmod +x Windows-binaries/* | |
zip -j release/fossa_${{ steps.get-version.outputs.VERSION }}_windows_amd64.zip Windows-binaries/fossa.exe | |
zip -j release/diagnose_${{ steps.get-version.outputs.VERSION }}_windows_amd64.zip Windows-binaries/diagnose.exe | |
zip -j release/millhone_${{ steps.get-version.outputs.VERSION }}_windows_amd64.zip Windows-binaries/millhone.exe | |
- name: Create checksums | |
# We have to run from within the release dir so that "release" isn't prepended to the relative path of the zip file. | |
run: | | |
cd release | |
sha256sum --binary "fossa_${{ steps.get-version.outputs.VERSION }}_linux_amd64.zip" > "fossa_${{ steps.get-version.outputs.VERSION }}_linux_amd64.zip.sha256" | |
sha256sum --binary "fossa_${{ steps.get-version.outputs.VERSION }}_linux_amd64.tar.gz" > "fossa_${{ steps.get-version.outputs.VERSION }}_linux_amd64.tar.gz.sha256" | |
sha256sum --binary "fossa_${{ steps.get-version.outputs.VERSION }}_darwin_amd64.zip" > "fossa_${{ steps.get-version.outputs.VERSION }}_darwin_amd64.zip.sha256" | |
sha256sum --binary "fossa_${{ steps.get-version.outputs.VERSION }}_darwin_arm64.zip" > "fossa_${{ steps.get-version.outputs.VERSION }}_darwin_arm64.zip.sha256" | |
sha256sum --binary "fossa_${{ steps.get-version.outputs.VERSION }}_windows_amd64.zip" > "fossa_${{ steps.get-version.outputs.VERSION }}_windows_amd64.zip.sha256" | |
echo "Sanity-checking the checksums." | |
cat *.sha256 | sha256sum --check --status | |
# Uploads the generated archives (tar.gz/zip) as build artifacts to allow | |
# verifying them without needing to do an actual release. This step does not | |
# need to run for tagged release versions. | |
- name: Upload release archives | |
if: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: release-archives | |
path: release | |
- name: Release | |
if: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
uses: softprops/action-gh-release@v1 | |
with: | |
files: release/* | |
draft: true | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |