CLI bundles #5
This file contains hidden or 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
| name: CLI bundles | |
| # Assemble the user-facing CLI packages: compiler + solvers + globalizer, findMUS | |
| # and mzn-analyse, then attach them to the release they were built from. | |
| # | |
| # Deliberately NOT part of ci.yml. Those three tools build *after* libminizinc in | |
| # the develop chain (libminizinc -> mzn-analyse -> FindMUS), so packaging during | |
| # libminizinc's own run could only ever pick up the previous cycle's tools. The | |
| # last link in the chain dispatches this instead, once everything exists. | |
| # | |
| # Nothing is compiled here: every input is downloaded from a published release. | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release: | |
| description: "Release to package and attach to (blank = edge)." | |
| type: string | |
| default: "" | |
| workflow_call: | |
| inputs: | |
| release: | |
| type: string | |
| default: "" | |
| permissions: | |
| contents: write | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| jobs: | |
| package: | |
| name: package (${{ matrix.platform }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { platform: linux, triple: x86_64-linux-gnu, runner: ubuntu-24.04 } | |
| - { platform: linux-arm64, triple: aarch64-linux-gnu, runner: ubuntu-24.04-arm } | |
| # musl packages on a glibc host: package_cli.sh only copies, strips and | |
| # archives, so it never has to run the binaries it packages. | |
| - { platform: musl, triple: x86_64-linux-musl, runner: ubuntu-24.04 } | |
| - { platform: musl-arm64, triple: aarch64-linux-musl, runner: ubuntu-24.04-arm } | |
| - { platform: osx, triple: aarch64-apple-darwin, runner: macos-14 } | |
| - { platform: win64, triple: x86_64-windows, runner: windows-2022 } | |
| - { platform: win64-arm, triple: aarch64-windows, runner: windows-11-arm } | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Resolve the release | |
| id: rel | |
| shell: bash | |
| run: | | |
| ref="${{ inputs.release }}" | |
| [ -n "$ref" ] || ref=edge | |
| echo "ref=$ref" >> "$GITHUB_OUTPUT" | |
| # Version stamped into the package name: the tag, or this run. | |
| if [ "$ref" = edge ]; then | |
| echo "version=build${{ github.run_id }}" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "version=$ref" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Fetch the compiler | |
| shell: bash | |
| run: | | |
| set -eux | |
| mkdir -p minizinc | |
| gh release download "${{ steps.rel.outputs.ref }}" --repo "$GITHUB_REPOSITORY" \ | |
| --pattern "minizinc-compiler-only-${{ matrix.triple }}.tar.gz" --dir . --clobber | |
| tar -xzf "minizinc-compiler-only-${{ matrix.triple }}.tar.gz" -C minizinc | |
| # vendor.lock travels with the release, so the solvers match the compiler. | |
| gh release download "${{ steps.rel.outputs.ref }}" --repo "$GITHUB_REPOSITORY" \ | |
| --pattern "vendor.lock" --dir . --clobber | |
| - name: Fetch pinned solvers | |
| shell: bash | |
| run: bash scripts/fetch_vendor.sh ${{ matrix.triple }} gecode chuffed highs or-tools | |
| - name: Fetch the bundled tools | |
| shell: bash | |
| run: | | |
| set -eux | |
| ref="${{ steps.rel.outputs.ref }}" | |
| # findMUS and mzn-analyse version with MiniZinc; globalizer is pinned. | |
| for tool in findMUS:FindMUS mzn-analyse:mzn-analyse; do | |
| dir="${tool%%:*}"; repo="${tool##*:}" | |
| mkdir -p "$dir" | |
| gh release download "$ref" --repo "MiniZinc/$repo" \ | |
| --pattern "${dir}-${{ matrix.triple }}.tar.gz" --dir . --clobber | |
| tar -xzf "${dir}-${{ matrix.triple }}.tar.gz" -C "$dir" | |
| done | |
| gver="$(grep -E '^globalizer=' vendor.lock | head -1 | cut -d= -f2-)" | |
| [ -n "$gver" ] || { echo "no version pinned for 'globalizer' in vendor.lock" >&2; exit 1; } | |
| # GHC cannot target Windows ARM64, so Globalizer has no build there. That | |
| # is the only permitted absence: anywhere else a missing asset fails. | |
| if [ "${{ matrix.triple }}" != aarch64-windows ]; then | |
| mkdir -p globalizer | |
| gh release download "$gver" --repo MiniZinc/Globalizer \ | |
| --pattern "globalizer-${{ matrix.triple }}.tar.gz" --dir . --clobber | |
| tar -xzf "globalizer-${{ matrix.triple }}.tar.gz" -C globalizer | |
| fi | |
| - name: Build CLI package | |
| shell: bash | |
| run: ROOT="$PWD" bash scripts/package_cli.sh "${{ matrix.triple }}" "${{ steps.rel.outputs.version }}" | |
| - name: Smoke test the package | |
| shell: bash | |
| run: | | |
| set -eux | |
| pkg=$(ls -d MiniZinc-*-${{ matrix.triple }}) | |
| check='set -eu | |
| out=$("$1/bin/minizinc" --solvers) | |
| echo "$out" | |
| for s in gecode chuffed cp-sat highs; do | |
| echo "$out" | grep -qi "$s" || { echo "missing solver: $s" >&2; exit 1; } | |
| done' | |
| case "${{ matrix.triple }}" in | |
| *musl) | |
| # A musl binary cannot run on the glibc host that packaged it, so | |
| # check it in Alpine. The bare image has no libstdc++/libgcc, which | |
| # the compiler links against. | |
| docker run --rm -v "$PWD:/w" -w /w alpine:3.20 \ | |
| sh -c "apk add --no-cache libstdc++ >/dev/null; $check" _ "$pkg" ;; | |
| *) | |
| sh -c "$check" _ "$pkg" ;; | |
| esac | |
| - name: Attach to the release | |
| shell: bash | |
| run: gh release upload "${{ steps.rel.outputs.ref }}" dist/* --clobber --repo "$GITHUB_REPOSITORY" | |
| # Bundle names embed the run id, so --clobber never removes the previous set. | |
| # Runs after every platform has uploaded, so a failure cannot leave the release | |
| # with neither the old bundles nor the new ones. | |
| prune: | |
| needs: package | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Drop superseded bundles | |
| shell: bash | |
| run: | | |
| set -eux | |
| ref="${{ inputs.release }}"; [ -n "$ref" ] || ref=edge | |
| # Tagged releases have stable names and keep what they have. | |
| [ "$ref" = edge ] || exit 0 | |
| keep="MiniZinc-build${{ github.run_id }}-" | |
| gh release view "$ref" --repo "$GITHUB_REPOSITORY" --json assets --jq '.assets[].name' \ | |
| | while read -r a; do | |
| case "$a" in | |
| MiniZinc-*) | |
| case "$a" in | |
| "$keep"*) ;; | |
| *) gh release delete-asset "$ref" "$a" -y --repo "$GITHUB_REPOSITORY" ;; | |
| esac ;; | |
| esac | |
| done | |
| # The images are built from the bundles this workflow just published. | |
| images: | |
| needs: [package, prune] | |
| uses: ./.github/workflows/docker.yml | |
| with: | |
| release: ${{ inputs.release }} | |
| permissions: | |
| contents: read | |
| packages: write |