From 077ef76055568655b31cde3308c40d84012f8f88 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Tue, 27 May 2025 17:49:34 -1000 Subject: [PATCH] ;ci:linux: add binaries-linux-arm64-stack, best effort --- .../workflows/binaries-linux-arm64-stack.yml | 207 ++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 .github/workflows/binaries-linux-arm64-stack.yml diff --git a/.github/workflows/binaries-linux-arm64-stack.yml b/.github/workflows/binaries-linux-arm64-stack.yml new file mode 100644 index 000000000..168dd4c4c --- /dev/null +++ b/.github/workflows/binaries-linux-arm64-stack.yml @@ -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 < ~/.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