Repository navigation
Address third round of OpenCodeReview findings on the packaging PR #10
Workflow file for this run
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: Build Linux | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| binary_list: | ||
| required: true | ||
| type: string | ||
| workflow_dispatch: | ||
| inputs: | ||
| binary_list: | ||
| description: 'Binaries bundled into the plain tar.gz artifacts (packaged debs/rpms always ship the full set)' | ||
| required: false | ||
| type: string | ||
| default: 'api-blockchain-scanner-daemon,api-web-server,dns-server,node-daemon,wallet-address-generator,wallet-cli,wallet-rpc-daemon' | ||
| concurrency: | ||
| group: release_linux-${{ github.ref }} | ||
| cancel-in-progress: true | ||
| env: | ||
| # Container image pins live in packaging/images.env (shared with | ||
| # packaging/test-local.sh) and are sourced by the steps that need them. | ||
| # Debian's builder also runs a full cargo build inside debian:12 in | ||
| # packaging/test-local.sh. | ||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-22.04 | ||
| timeout-minutes: 180 | ||
| permissions: | ||
| contents: read | ||
| permissions: | ||
| contents: read | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| arch: [aarch64, x86_64] | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| with: | ||
| submodules: recursive | ||
| fetch-depth: 0 # git describe needs history for the dispatch fallback version | ||
| persist-credentials: false # the checkout is only built, never pushed | ||
| # Register qemu binfmt handlers so `docker run --platform linux/arm64` | ||
| # works on the arm64 matrix leg (needed for the debian:12 deb builder). | ||
| - uses: docker/setup-qemu-action@v3 | ||
| - name: Extract version from tag | ||
| id: get_version | ||
| run: | | ||
| VERSION=${GITHUB_REF#refs/tags/} | ||
| VERSION=${VERSION#v} | ||
| if [ "$VERSION" = "$GITHUB_REF" ]; then | ||
| VERSION="$(git describe --tags --abbrev=0 2>/dev/null | sed -e 's/^v//' || true)" | ||
| fi | ||
| if [ -z "$VERSION" ]; then | ||
| VERSION="0.0.0-ci" | ||
| fi | ||
| # Validate the grammar up front, so a non-semver tag fails here with a clear message | ||
| # instead of deep inside a packaging script (the same grammar the builders enforce). | ||
| if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'; then | ||
| echo "derived version '$VERSION' is not X.Y.Z[-suffix]; tag a semver release" >&2 | ||
| exit 1 | ||
| fi | ||
| echo "VERSION=$VERSION" >> $GITHUB_OUTPUT | ||
| echo "Version extracted: $VERSION" | ||
| - name: Set up Rust | ||
| uses: dtolnay/rust-toolchain@stable | ||
| with: | ||
| toolchain: stable | ||
| targets: ${{ matrix.arch }}-unknown-linux-gnu | ||
| - name: Install cross-compilation tools | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu | ||
| - name: Install build dependencies | ||
| run: | | ||
| if [ "${{ matrix.arch }}" = "aarch64" ]; then | ||
| sudo dpkg --add-architecture arm64 | ||
| sudo sed -i -E 's/^deb /deb [arch=amd64] /' /etc/apt/sources.list | ||
| { | ||
| echo 'deb [arch=arm64 signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse' | ||
| echo 'deb [arch=arm64 signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse' | ||
| echo 'deb [arch=arm64 signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse' | ||
| echo 'deb [arch=arm64 signed-by=/usr/share/keyrings/ubuntu-archive-keyring.gpg] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted universe multiverse' | ||
| } | sudo tee /etc/apt/sources.list.d/ubuntu-ports-arm64.list > /dev/null | ||
| sudo apt-get update | ||
| sudo apt-get install -y \ | ||
| gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \ | ||
| libdbus-1-dev:arm64 \ | ||
| libusb-1.0-0-dev:arm64 \ | ||
| libudev-dev:arm64 | ||
| else | ||
| sudo apt-get update | ||
| sudo apt-get install -y \ | ||
| libdbus-1-dev \ | ||
| libusb-1.0-0-dev \ | ||
| libudev-dev | ||
| fi | ||
| sudo apt-get install -y zip pkg-config | ||
| - name: Build | ||
| env: | ||
| PKG_CONFIG_ALLOW_CROSS_aarch64_unknown_linux_gnu: "1" | ||
| PKG_CONFIG_LIBDIR_aarch64_unknown_linux_gnu: "/usr/lib/aarch64-linux-gnu/pkgconfig:/usr/share/pkgconfig" | ||
| run: | | ||
| cargo build --release --locked --target ${{ matrix.arch }}-unknown-linux-gnu --features trezor,ledger | ||
| # Shared hicolor icon set for the GUI packages (deb and rpm builders | ||
| # consume it; avoids ImageMagick in the fedora container). | ||
| - name: Pre-generate icons | ||
| run: | | ||
| docker run --rm --platform linux/${{ matrix.arch }} -v "$PWD":/work -w /work debian:12 \ | ||
| bash -ec " | ||
| export DEBIAN_FRONTEND=noninteractive | ||
| apt-get update -qq && apt-get install -y -qq imagemagick >/dev/null | ||
| packaging/make-icons.sh build-tools/assets/node-gui-icon_512.png dist/assets/icons | ||
| " | ||
| # GH-hosted ubuntu runners ship qemu-user-static + binfmt, so | ||
| # `docker run --platform linux/arm64` works out of the box: the arm64 leg | ||
| # runs the deb builder inside an arm64 debian:12 container. The same | ||
| # scripts run locally via packaging/test-local.sh. | ||
| - name: Create Debian packages | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| ARCH=${{ matrix.arch }} | ||
| if [ "$ARCH" = "x86_64" ]; then DEBARCH=amd64; else DEBARCH=arm64; fi | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work debian:12 \ | ||
| packaging/deb/build.sh \ | ||
| --package node --version "$VERSION" \ | ||
| --debarch $DEBARCH \ | ||
| --binaries-dir /work/target/$ARCH-unknown-linux-gnu/release \ | ||
| --out /work/dist | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work debian:12 \ | ||
| packaging/deb/build.sh \ | ||
| --package gui --version "$VERSION" \ | ||
| --debarch $DEBARCH \ | ||
| --gui-binary /work/target/$ARCH-unknown-linux-gnu/release/node-gui \ | ||
| --repo-root /work --out /work/dist | ||
| # Arch-matched container (qemu on the arm64 leg): native strip works and | ||
| # the binaries run under emulation so help2man generates real man pages. | ||
| - name: Create RPM packages | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| source packaging/images.env | ||
| ARCH=${{ matrix.arch }} | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work $FEDORA_IMAGE \ | ||
| packaging/rpm/build.sh \ | ||
| --package node --rpmarch $ARCH \ | ||
| --version "$VERSION" \ | ||
| --binaries-dir /work/target/$ARCH-unknown-linux-gnu/release \ | ||
| --out /work/dist | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work $FEDORA_IMAGE \ | ||
| packaging/rpm/build.sh \ | ||
| --package gui --rpmarch $ARCH \ | ||
| --version "$VERSION" \ | ||
| --gui-binary /work/target/$ARCH-unknown-linux-gnu/release/node-gui \ | ||
| --repo-root /work --out /work/dist | ||
| # Install smoke tests in fresh containers (same images as production use) | ||
| - name: Smoke test Debian packages | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| ARCH=${{ matrix.arch }} | ||
| if [ "$ARCH" = "x86_64" ]; then DEBARCH=amd64; else DEBARCH=arm64; fi | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work debian:12 \ | ||
| packaging/checks/smoke-deb.sh dist/Mintlayer_Node_linux_${VERSION}_${DEBARCH}.deb mintlayer-node node | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work debian:12 \ | ||
| packaging/checks/smoke-deb.sh dist/Mintlayer_Node_GUI_linux_${VERSION}_${DEBARCH}.deb mintlayer-node-gui gui | ||
| - name: Smoke test RPM packages | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| ARCH=${{ matrix.arch }} | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work $FEDORA_IMAGE \ | ||
| packaging/checks/smoke-rpm.sh dist/Mintlayer_Node_linux_${VERSION}_${ARCH}.rpm mintlayer-node node | ||
| docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work $FEDORA_IMAGE \ | ||
| packaging/checks/smoke-rpm.sh dist/Mintlayer_Node_GUI_linux_${VERSION}_${ARCH}.rpm mintlayer-node-gui gui | ||
| # Arch images are amd64-only: the x86_64 leg is arch-matched (native | ||
| # strip, ldd-based dependencies, help2man man pages), the arm64 leg | ||
| # repackages cross-target with stubs — same as the local rpm legs. | ||
| - name: Create Arch packages | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| source packaging/images.env | ||
| ARCH=${{ matrix.arch }} | ||
| docker run --rm -v "$PWD":/work -w /work $ARCH_IMAGE \ | ||
| packaging/arch/build.sh \ | ||
| --package node --arch "$ARCH" \ | ||
| --version "$VERSION" \ | ||
| --binaries-dir /work/target/$ARCH-unknown-linux-gnu/release \ | ||
| --out /work/dist | ||
| docker run --rm -v "$PWD":/work -w /work $ARCH_IMAGE \ | ||
| packaging/arch/build.sh \ | ||
| --package gui --arch "$ARCH" \ | ||
| --version "$VERSION" \ | ||
| --gui-binary /work/target/$ARCH-unknown-linux-gnu/release/node-gui \ | ||
| --repo-root /work --out /work/dist | ||
| # x86_64 leg: arch-matched container (native strip, ldd-based | ||
| # dependencies, help2man man pages), so the package installs natively. | ||
| # aarch64 leg: the same amd64-only image installs the foreign-arch | ||
| # package with IgnoreArch and runs the binaries through the qemu binfmt | ||
| # handlers registered above — the same emulation the deb/rpm legs use | ||
| # for their arm64 smoke tests. | ||
| - name: Smoke test Arch packages | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| source packaging/images.env | ||
| ARCH=${{ matrix.arch }} | ||
| docker run --rm -v "$PWD":/work -w /work $ARCH_IMAGE \ | ||
| packaging/checks/smoke-arch.sh dist/Mintlayer_Node_linux_${VERSION}_${ARCH}.pkg.tar.zst mintlayer-node node "$ARCH" | ||
| docker run --rm -v "$PWD":/work -w /work $ARCH_IMAGE \ | ||
| packaging/checks/smoke-arch.sh dist/Mintlayer_Node_GUI_linux_${VERSION}_${ARCH}.pkg.tar.zst mintlayer-node-gui gui "$ARCH" | ||
| - name: Package Mintlayer Node (without GUI) as tar.gz | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| BINARY_LIST: ${{ inputs.binary_list }} | ||
| run: | | ||
| mkdir -p Mintlayer_Node_linux_${VERSION}_${{ matrix.arch }} | ||
| IFS=',' read -ra BINARIES <<< "$BINARY_LIST" | ||
| for binary in "${BINARIES[@]}"; do | ||
| cp target/${{ matrix.arch }}-unknown-linux-gnu/release/$binary Mintlayer_Node_linux_${VERSION}_${{ matrix.arch }}/mintlayer-$binary | ||
| done | ||
| tar -czvf Mintlayer_Node_linux_${VERSION}_${{ matrix.arch }}.tar.gz Mintlayer_Node_linux_${VERSION}_${{ matrix.arch }} | ||
| - name: Package Mintlayer Node GUI as tar.gz | ||
| env: | ||
| VERSION: ${{ steps.get_version.outputs.VERSION }} | ||
| run: | | ||
| mkdir -p Mintlayer_Node_GUI_linux_${VERSION}_${{ matrix.arch }} | ||
| cp target/${{ matrix.arch }}-unknown-linux-gnu/release/node-gui Mintlayer_Node_GUI_linux_${VERSION}_${{ matrix.arch }}/mintlayer-node-gui | ||
| tar -czvf Mintlayer_Node_GUI_linux_${VERSION}_${{ matrix.arch }}.tar.gz Mintlayer_Node_GUI_linux_${VERSION}_${{ matrix.arch }} | ||
| - name: Upload Node DEB Artifact (without GUI) | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_deb | ||
| path: dist/Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}.deb | ||
| - name: Upload GUI DEB Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_deb | ||
| path: dist/Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}.deb | ||
| - name: Upload Node RPM Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_rpm | ||
| path: dist/Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}.rpm | ||
| - name: Upload GUI RPM Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_rpm | ||
| path: dist/Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}.rpm | ||
| - name: Upload Node PKG Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_pkg | ||
| path: dist/Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}.pkg.tar.zst | ||
| - name: Upload GUI PKG Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_pkg | ||
| path: dist/Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}.pkg.tar.zst | ||
| - name: List tar.gz files | ||
| run: | | ||
| echo "Matching tar.gz files:" | ||
| ls -l Mintlayer_Node_linux_*.tar.gz | ||
| - name: Upload Node GUI tar.gz Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| continue-on-error: true | ||
| with: | ||
| name: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_tar.gz | ||
| path: Mintlayer_Node_GUI_linux_*.tar.gz | ||
| - name: Upload Node tar.gz Artifact (without GUI) | ||
| uses: actions/upload-artifact@v4 | ||
| continue-on-error: true | ||
| with: | ||
| name: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_tar.gz | ||
| path: Mintlayer_Node_linux_*.tar.gz | ||