Skip to content

escape the separator #3766

escape the separator

escape the separator #3766

Workflow file for this run

# 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 }}
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'
rust-features: jemalloc
- 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'
# 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).
# Non-Linux environments generally don't need `jemalloc`
# and in particular Windows doesn't support it
rust-features: jemalloc
# 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 action installs the 'minimal' profile.
# Even on Linux ARM this is necessary because rust-cache uses it.
- uses: dtolnay/rust-toolchain@stable
- name: Install additional Rust tooling
if: ${{ matrix.os != 'LinuxARM' }}
uses: taiki-e/install-action@v2
with:
tool: nextest
- uses: Swatinem/rust-cache@v2
with:
prefix-key: ${{ matrix.os }}
# The home directory inside containers is different than the one outside of them.
# LinuxARM needs this for its caching to work inside haskell-static-alpine.
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"
- name: Build Rust dependencies
if: ${{ matrix.os != 'LinuxARM' }}
env:
RUST_FEATURES: ${{ matrix.rust-features }}
run: |
cargo build ${RUST_FEATURES:+--features $RUST_FEATURES} --release
# Run tests in release mode to reduce the need for rebuilds.
- name: Test Rust dependencies
if: ${{ matrix.os != 'LinuxARM' }}
run: cargo nextest run --release
- name: Validate diagnose commands run on the platform
if: ${{ matrix.os != 'LinuxARM' }}
run: |
cargo run --release --bin diagnose -- walk --trace-spans none --trace-level info
- 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 }}-${{ matrix.ghc }}-dist-newstyle-${{ github.sha }}
restore-keys: |
${{ matrix.os-name }}-${{ matrix.ghc }}-dist-newstyle-${{ env.parent_commit }}
${{ matrix.os-name }}-${{ matrix.ghc }}-dist-newstyle-
${{ matrix.os-name }}-${{ matrix.ghc }}-
- 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 }} ${{ matrix.rust-features }}
- name: Build and Unit Test
if: ${{ matrix.os != 'LinuxARM' }}
run: ./.github/workflows/scripts/build.sh ${{ runner.os }} ${{ matrix.project-file }}
# Test cabal-install
# TODO: This has apparently not been turned on for a while since no matrix.os contains 'linux'.
# When I make it function it causes an error.
# This is something I need to look into in the future.
- name: Test Cabal Install (Linux)
if: ${{ matrix.os == 'linux' }}
run: cabal install --overwrite-policy=always --project=${{ matrix.project-file }} --ghc-options="-Wwarn"
# 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
# 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
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
tar --append --file "$LINUX_ARM_FOSSA_TAR_PATH" --directory Linux-arm-binaries fossa.bundle
tar --append --file "$LINUX_ARM_DIAGNOSE_TAR_PATH" --directory Linux-arm-binaries diagnose.bundle
tar --append --file "$LINUX_ARM_MILLHONE_TAR_PATH" --directory Linux-arm-binaries millhone.bundle
zip -j "$LINUX_ARM_FOSSA_ZIP_PATH" Linux-arm-binaries/fossa.bundle
zip -j "$LINUX_ARM_DIAGNOSE_ZIP_PATH" Linux-arm-binaries/diagnose.bundle
zip -j "$LINUX_ARM_MILLHONE_ZIP_PATH" Linux-arm-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
for f in fossa*.zip fossa*.tar.gz
do
sha256sum --binary "$f" > "$f.sha256"
done
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 }}