;ci:linux: add binaries-linux-arm64-stack, best effort

This commit is contained in:
Simon Michael 2025-05-27 17:49:34 -10:00
parent c8ab9e8bf6
commit 077ef76055

View File

@ -0,0 +1,207 @@
# TRIGGER: Runs on any push to binaries-linux-arm64-stack or binaries branches.
# ACTION: Builds, unit-tests and saves linux arm64 static binaries with stack and the resolver & ghc version below and Alpine linux,
# which provides the statically-linkable musl.
name: binaries-linux-arm64-stack
on:
push:
branches: [ binaries-linux-arm64-stack, binaries ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
container: alpine:latest
steps:
- name: Show platform info
run: |
arch
uname -a
- name: Check out
uses: actions/checkout@v4
# have to fetch everything for git describe for --version
with:
fetch-depth: 0
# - name: Check embedded files
# run: |
# apt install ripgrep
# tools/checkembeddedfiles
# things to be cached/restored:
# - name: process cache of ghcup-installed tools
# id: ghcup
# uses: actions/cache@v4
# with:
# path: ~/.ghcup
# key: ${{ runner.os }}-ghcup-${{ hashFiles('**.yaml') }}
# restore-keys: |
# ${{ runner.os }}-ghcup
- name: process cache of stack-installed programs in ~/.local/bin
id: stack-programs
uses: actions/cache@v4
with:
path: ~/.local/bin
key: ${{ runner.os }}-aarch64-stack-programs-${{ hashFiles('**.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-stack-programs
- name: process cache of stack global package db
id: stack-global
uses: actions/cache@v4
with:
path: ~/.stack
key: ${{ runner.os }}-aarch64-stack-global-${{ hashFiles('**.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-stack-global
- name: process cache of .stack-work
uses: actions/cache@v4
with:
path: .stack-work
key: ${{ runner.os }}-aarch64-stack-work-${{ hashFiles('**.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-stack-work
- name: process cache of hledger-lib/.stack-work
uses: actions/cache@v4
with:
path: hledger-lib/.stack-work
key: ${{ runner.os }}-aarch64-hledger-lib-stack-work-${{ hashFiles('hledger-lib/package.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-hledger-lib-stack-work
- name: process cache of hledger/.stack-work
uses: actions/cache@v4
with:
path: hledger/.stack-work
key: ${{ runner.os }}-aarch64-hledger-stack-work-${{ hashFiles('hledger/package.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-hledger-stack-work
- name: process cache of hledger-ui/.stack-work
uses: actions/cache@v4
with:
path: hledger-ui/.stack-work
key: ${{ runner.os }}-aarch64-hledger-ui-stack-work-${{ hashFiles('hledger-ui/package.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-hledger-ui-stack-work
- name: process cache of hledger-web/.stack-work
uses: actions/cache@v4
with:
path: hledger-web/.stack-work
key: ${{ runner.os }}-aarch64-hledger-web-stack-work-${{ hashFiles('hledger-web/package.yaml') }}
restore-keys: |
${{ runner.os }}-aarch64-hledger-web-stack-work
# actions:
# - name: Install general tools with system package manager
# run: |
# apk --no-cache add binutils-gold curl gcc g++ git ripgrep tar gmp-dev libffi-dev ncurses-dev ncurses-static zlib-dev zlib-static
# set HOME to /root for stack (do it here in case it matters for ghcup too). workaround from https://github.com/actions/runner/issues/863)
- name: Set $HOME to /root for stack
run: |
apk add sudo
echo "setting HOME=/root for stack"
echo HOME=/root | sudo tee -a $GITHUB_ENV
- name: Install System Dependencies
run: |
# Add dependencies GHC/Stack need for linking
apk add stack gmp-dev zlib-dev zlib-static libffi-dev ncurses-dev ncurses-static gcc make musl-dev xz ripgrep
- name: Configure stack.yaml for static linking
run: |
# Add the ghc-options section to stack.yaml, using "$all"
echo "ghc-options:" >> stack.yaml
echo ' "$all": -fPIC -static -pie -Werror' >> stack.yaml
echo "Applied new stack.yaml configuration:"
cat stack.yaml
# - name: Install haskell tools if needed
# run: |
# Try hard to persuade ghcup to install an aarch64 binary
#ghcup config set platform-override '{ "arch": "A_64", "platform": { "contents": "Alpine", "tag": "Linux" }, "version": "3.18" }'
# cat >~/.ghcup/config.yaml <<END
# platform-override:
# arch: A_64
# platform:
# contents: Alpine
# tag: Linux
# version: '3.18'
# END
# if [[ ! -x ~/.ghcup/bin/ghc-9.12.2 ]]; then ~/.ghcup/bin/ghcup install ghc 9.12.2 -u https://downloads.haskell.org/~ghc/9.12.2/ghc-9.12.2-aarch64-alpine3_18-linux.tar.xz && ~/.ghcup/bin/ghcup set ghc 9.12.2; fi; printf "ghc: "; ghc --version
# if [[ ! -x ~/.ghcup/bin/cabal ]]; then ~/.ghcup/bin/ghcup install cabal 3.14.2.0 && ~/.ghcup/bin/ghcup set cabal 3.14.2.0; fi; printf "cabal: "; cabal --version
# curl -sSL https://get.haskellstack.org/ | sh
# # cat > ~/.stack/global-project/stack.yaml << END
# # packages: []
# # resolver: nightly-2025-05-01
# # compiler: ghc-9.12.2
# # notify-if-ghc-untested: false
# # notify-if-cabal-untested: false
# # END
# stack --allow-different-user setup --install-ghc
# --allow-different-user is needed because of #863 above (or because stack didn't notice we're in a docker container)
- name: List dep versions
run: |
stack exec -- ghc-pkg list
- name: Build with stack and run unit tests
run: |
# stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger # || (echo "ERROR: building hledger failed"; false)
# stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger-ui # || (echo "ERROR: building hledger-ui failed"; false)
# stack --allow-different-user build --test --ghc-options='-fPIC -optl-static -Werror' hledger-web # || (echo "ERROR: building hledger-web failed"; false)
stack --allow-different-user install --test --ghc-options='-Werror' hledger # || (echo "ERROR: building hledger failed"; false)
# stack --allow-different-user install --test --ghc-options='-Werror' hledger-ui # || (echo "ERROR: building hledger-ui failed"; false)
# stack --allow-different-user install --test --ghc-options='-Werror' hledger-web # || (echo "ERROR: building hledger-web failed"; false)
# - name: Build static hledger binary
# run: |
# # --allow-different-user is needed because you are root in the container
# # It's good practice to clean after a major flag change.
# # stack --allow-different-user clean
# stack --allow-different-user build --test
- name: Verify the binary
run: |
# Find the built executable and check if it's a static binary
BINARY_PATH=$(stack --allow-different-user exec -- which hledger)
echo "Binary is at: $BINARY_PATH"
echo "Checking linkage:"
# The output of ldd should be "statically linked" or "not a dynamic executable"
ldd "$BINARY_PATH"
- name: Gather binaries
run: |
mkdir tmp
cp ~/.local/bin/hledger tmp
cp ~/.local/bin/hledger-ui tmp
cp ~/.local/bin/hledger-web tmp
cp hledger/embeddedfiles/*.1 tmp
cp hledger/embeddedfiles/*.info tmp
cp hledger/shell-completion/hledger-completion.bash tmp
strip tmp/hledger
strip tmp/hledger-ui
strip tmp/hledger-web
cd tmp
tar cvf hledger-linux-arm64.tar hledger hledger-ui hledger-web *.1 *.info hledger-completion.bash
./hledger --version
./hledger-ui --version
./hledger-web --version
# upload-artifact loses execute permissions, so we tar the binaries to preserve them.
# github UI always zips artifacts when they are downloaded, so we don't bother compressing the tar.
# Unfortunately it means users must both unzip and untar.
- name: Upload binaries
uses: actions/upload-artifact@v4
with:
name: hledger-linux-arm64
path: tmp/hledger-linux-arm64.tar