Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 107 additions & 137 deletions .github/workflows/release_linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,52 @@ on:
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
Comment on lines +17 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · medium
cancel-in-progress: true on a release workflow means a new tag push or dispatch while a release build is running will cancel the in-flight build — potentially mid-way through uploads (triggering tag pushes, e.g. by release automation, make this realistic). For release/tag-triggered workflows, cancellation of a partially-published release is usually worse than a redundant run. Consider scoping cancellation to non-tag events, or setting cancel-in-progress: false.


env:
FEDORA_IMAGE: fedora:44 # pinned for reproducible packaging; bump deliberately

jobs:
build:
runs-on: ubuntu-22.04
Comment on lines 24 to 26

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security · medium
This workflow has no permissions: block, so jobs run with the repository's default (potentially broad) GITHUB_TOKEN permissions. The build job only needs to upload artifacts; declare least-privilege permissions explicitly.

Suggestion:

Suggested change
jobs:
build:
runs-on: ubuntu-22.04
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-22.04

timeout-minutes: 180
permissions:
contents: read
strategy:
fail-fast: false
Comment on lines 24 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

other · medium
The QEMU-emulated arm64 deb/rpm container builds are slow, and there is no timeout-minutes on the job nor a concurrency group — a hung emulated build can run indefinitely, and simultaneous tag pushes/dispatches spawn duplicate expensive runs. Add a job-level timeout and a concurrency group (e.g. keyed on ref).

Suggestion:

Suggested change
jobs:
build:
runs-on: ubuntu-22.04
strategy:
fail-fast: false
jobs:
build:
runs-on: ubuntu-22.04
timeout-minutes: 120
concurrency:
group: release-linux-${{ github.ref }}
cancel-in-progress: false
strategy:
fail-fast: false

matrix:
arch: [aarch64, x86_64]
steps:
- uses: actions/checkout@v5
with:
submodules: recursive
Comment on lines 35 to 37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · high
actions/checkout@v5 defaults to fetch-depth: 1, which does not fetch tags. On workflow_dispatch (non-tag ref), git describe --tags --abbrev=0 will fail and every package silently builds as version 0.0.0-ci; if tags are partially available it could also pick a stale previous-release tag and mislabel published artifacts. Add fetch-depth: 0 to the checkout step so the describe fallback resolves the real latest tag.

Suggestion:

Suggested change
- uses: actions/checkout@v5
with:
submodules: recursive
- uses: actions/checkout@v5
with:
submodules: recursive
fetch-depth: 0

fetch-depth: 0 # git describe needs history for the dispatch fallback version

# 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
Comment on lines +52 to +54

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug · medium
The 0.0.0-ci fallback (and the git describe fallback above it) silently proceeds to package, smoke-test, and upload artifacts with a placeholder or possibly-wrong version. Because artifact and file names are keyed on this version, a placeholder build can publish misleadingly named release artifacts, and two different fallback runs collide on the same artifact names. Consider failing the job (or at least warning) when the version cannot be derived from a tag.

Suggestion:

Suggested change
if [ -z "$VERSION" ]; then
VERSION="0.0.0-ci"
fi
if [ -z "$VERSION" ]; then
echo "::error::Could not derive version from tag or git describe"
exit 1
fi

echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "Version extracted: $VERSION"

Expand Down Expand Up @@ -62,13 +91,12 @@ jobs:
sudo apt-get update

sudo apt-get install -y \
rpm \
libdbus-1-dev \
libusb-1.0-0-dev \
libudev-dev
fi

sudo apt-get install -y debhelper zip imagemagick pkg-config
sudo apt-get install -y zip pkg-config

- name: Build
env:
Expand All @@ -77,129 +105,73 @@ jobs:
run: |
cargo build --release --locked --target ${{ matrix.arch }}-unknown-linux-gnu --features trezor,ledger

- name: Create Debian package for GUI
# 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: |
mkdir -p debian-gui/DEBIAN
mkdir -p debian-gui/usr/bin
mkdir -p debian-gui/usr/share/applications
mkdir -p debian-gui/usr/share/icons/hicolor/512x512/apps
mkdir -p debian-gui/usr/share/icons/hicolor/256x256/apps
mkdir -p debian-gui/usr/share/icons/hicolor/128x128/apps
mkdir -p debian-gui/usr/share/icons/hicolor/64x64/apps
cp target/${{ matrix.arch }}-unknown-linux-gnu/release/node-gui debian-gui/usr/bin/mintlayer-node-gui

# Copy and convert icon files
cp build-tools/assets/node-gui-icon_512.png debian-gui/usr/share/icons/hicolor/512x512/apps/mintlayer-node-gui.png
convert build-tools/assets/node-gui-icon_512.png -resize 256x256 debian-gui/usr/share/icons/hicolor/256x256/apps/mintlayer-node-gui.png
convert build-tools/assets/node-gui-icon_512.png -resize 128x128 debian-gui/usr/share/icons/hicolor/128x128/apps/mintlayer-node-gui.png
convert build-tools/assets/node-gui-icon_512.png -resize 64x64 debian-gui/usr/share/icons/hicolor/64x64/apps/mintlayer-node-gui.png

# Create .desktop file
cat << EOF > debian-gui/usr/share/applications/mintlayer-node-gui.desktop
[Desktop Entry]
Name=Mintlayer Node GUI
Exec=/usr/bin/mintlayer-node-gui
Icon=mintlayer-node-gui
Type=Application
Categories=Utility;Network;
EOF

cat << EOF > debian-gui/DEBIAN/control
Package: mintlayer-node-gui
Version: ${{ steps.get_version.outputs.VERSION }}
Section: utils
Priority: optional
Architecture: ${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}
Maintainer: Mintlayer <devs@mintlayer.org>
Description: Mintlayer Node GUI
A graphical user interface for the Mintlayer node.
EOF
dpkg-deb --build debian-gui
mv debian-gui.deb Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}.deb

- name: Create Debian package for Node (without GUI)
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
run: |
mkdir -p debian-node/DEBIAN
mkdir -p debian-node/usr/bin
IFS=',' read -ra BINARIES <<< "${{ inputs.binary_list }}"
for binary in "${BINARIES[@]}"; do
cp target/${{ matrix.arch }}-unknown-linux-gnu/release/$binary debian-node/usr/bin/mintlayer-$binary
done
cat << EOF > debian-node/DEBIAN/control
Package: mintlayer-node
Version: ${{ steps.get_version.outputs.VERSION }}
Section: utils
Priority: optional
Architecture: ${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}
Maintainer: Mintlayer <devs@mintlayer.org>
Description: Mintlayer Node
Mintlayer node and associated tools.
EOF
dpkg-deb --build debian-node
mv debian-node.deb Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}.deb

- name: Create RPM package for GUI
if: matrix.arch == 'x86_64'
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 "${{ steps.get_version.outputs.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 "${{ steps.get_version.outputs.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
run: |
mkdir -p rpm-gui/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
mkdir -p rpm-gui/BUILDROOT/mintlayer-node-gui-${{ steps.get_version.outputs.VERSION }}-1.x86_64
cp -r debian-gui/usr rpm-gui/BUILDROOT/mintlayer-node-gui-${{ steps.get_version.outputs.VERSION }}-1.x86_64/

cat << EOF > rpm-gui/SPECS/mintlayer-node-gui.spec
Name: mintlayer-node-gui
Version: ${{ steps.get_version.outputs.VERSION }}
Release: 1
Summary: Mintlayer Node GUI
License: MIT
BuildArch: x86_64

%description
A graphical user interface for the Mintlayer node.

%files
/usr/bin/mintlayer-node-gui
/usr/share/applications/mintlayer-node-gui.desktop
/usr/share/icons/hicolor/512x512/apps/mintlayer-node-gui.png
/usr/share/icons/hicolor/256x256/apps/mintlayer-node-gui.png
/usr/share/icons/hicolor/128x128/apps/mintlayer-node-gui.png
/usr/share/icons/hicolor/64x64/apps/mintlayer-node-gui.png

%changelog
* $(date "+%a %b %d %Y") Mintlayer <devs@mintlayer.org> - ${{ steps.get_version.outputs.VERSION }}-1
- Initial RPM release
EOF

rpmbuild -bb --define "_topdir $(pwd)/rpm-gui" --buildroot $(pwd)/rpm-gui/BUILDROOT/mintlayer-node-gui-${{ steps.get_version.outputs.VERSION }}-1.x86_64 rpm-gui/SPECS/mintlayer-node-gui.spec
mv rpm-gui/RPMS/x86_64/mintlayer-node-gui-${{ steps.get_version.outputs.VERSION }}-1.x86_64.rpm Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_x86_64.rpm

- name: Create RPM package for Node (without GUI)
if: matrix.arch == 'x86_64'
ARCH=${{ matrix.arch }}
docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work ${{ env.FEDORA_IMAGE }} \
packaging/rpm/build.sh \
--package node --rpmarch $ARCH \
--version "${{ steps.get_version.outputs.VERSION }}" \
--binaries-dir /work/target/$ARCH-unknown-linux-gnu/release \
--out /work/dist
docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work ${{ env.FEDORA_IMAGE }} \
packaging/rpm/build.sh \
--package gui --rpmarch $ARCH \
--version "${{ steps.get_version.outputs.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
run: |
mkdir -p rpm-node/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
mkdir -p rpm-node/BUILDROOT/mintlayer-node-${{ steps.get_version.outputs.VERSION }}-1.x86_64
cp -r debian-node/usr rpm-node/BUILDROOT/mintlayer-node-${{ steps.get_version.outputs.VERSION }}-1.x86_64/

cat << EOF > rpm-node/SPECS/mintlayer-node.spec
Name: mintlayer-node
Version: ${{ steps.get_version.outputs.VERSION }}
Release: 1
Summary: Mintlayer Node
License: MIT
BuildArch: x86_64

%description
Mintlayer node and associated tools.

%files
/usr/bin/*

%changelog
* $(date "+%a %b %d %Y") Mintlayer <devs@mintlayer.org> - ${{ steps.get_version.outputs.VERSION }}-1
- Initial RPM release
EOF

rpmbuild -bb --define "_topdir $(pwd)/rpm-node" --buildroot $(pwd)/rpm-node/BUILDROOT/mintlayer-node-${{ steps.get_version.outputs.VERSION }}-1.x86_64 rpm-node/SPECS/mintlayer-node.spec
mv rpm-node/RPMS/x86_64/mintlayer-node-${{ steps.get_version.outputs.VERSION }}-1.x86_64.rpm Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_x86_64.rpm
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_${{ steps.get_version.outputs.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_${{ steps.get_version.outputs.VERSION }}_${DEBARCH}.deb mintlayer-node-gui gui

- name: Smoke test RPM packages
run: |
ARCH=${{ matrix.arch }}
docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work ${{ env.FEDORA_IMAGE }} \
packaging/checks/smoke-rpm.sh dist/Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${ARCH}.rpm mintlayer-node node
docker run --rm --platform linux/$ARCH -v "$PWD":/work -w /work ${{ env.FEDORA_IMAGE }} \
packaging/checks/smoke-rpm.sh dist/Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${ARCH}.rpm mintlayer-node-gui gui

- name: Package Mintlayer Node (without GUI) as tar.gz
run: |
Expand All @@ -213,34 +185,32 @@ jobs:
- name: Package Mintlayer Node GUI as tar.gz
run: |
mkdir -p Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}
cp target/${{ matrix.arch }}-unknown-linux-gnu/release/node-gui Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}/mintlayer-node-gui
tar -czvf Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}.tar.gz Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}
cp target/${{ matrix.arch }}-unknown-linux-gnu/release/node-gui Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}/mintlayer-node-gui
tar -czvf Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}.tar.gz Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}

- name: Upload GUI DEB Artifact
- name: Upload Node DEB Artifact (without GUI)
uses: actions/upload-artifact@v4
with:
name: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_deb
path: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}.deb
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 Node DEB Artifact (without GUI)
- name: Upload GUI DEB Artifact
uses: actions/upload-artifact@v4
with:
name: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch }}_deb
path: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_${{ matrix.arch == 'x86_64' && 'amd64' || 'arm64' }}.deb
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 GUI RPM Artifact
if: matrix.arch == 'x86_64'
- name: Upload Node RPM Artifact
uses: actions/upload-artifact@v4
with:
name: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_x86_64_rpm
path: Mintlayer_Node_GUI_linux_${{ steps.get_version.outputs.VERSION }}_x86_64.rpm
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 Node RPM Artifact (without GUI)
if: matrix.arch == 'x86_64'
- name: Upload GUI RPM Artifact
uses: actions/upload-artifact@v4
with:
name: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_x86_64_rpm
path: Mintlayer_Node_linux_${{ steps.get_version.outputs.VERSION }}_x86_64.rpm
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: List tar.gz files
run: |
Expand Down
20 changes: 6 additions & 14 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,45 @@
**/target/
# These are backup files generated by rustfmt
**/*.rs.bk

.DS_Store

# Intellij IDEA
.idea/
*.iml
/customSpec.json

# VSCode
.vscode/

#exclude python env
env/

# ...but not the package environment-file templates
!packaging/common/env/
# Python cache
**/__pycache__

# Files generated for the testing system
test/config.ini

# The cache for docker container dependency
.cargo/*

# But do not ignore the cargo.toml file
!.cargo/config.toml

# The cache for chain data in container
.local

# direnv cache
.direnv

# Python compiled files
*.pyc

# wasm
wasm-wrappers/pkg/
wasm-wrappers/js-bindings-test/dist/

# 'mintlayer-data' will be mapped to home directories of docker containers, so everything
# inside it will be generated by the containers.
build-tools/docker/example-mainnet/mintlayer-data/*
# Same for example-mainnet-dns-server.
build-tools/docker/example-mainnet-dns-server/mintlayer-data/*

# This directory will contain some generated files.
build-tools/block-data-plots/output

# Cloudflare wrangler local cache (created by local wrangler tooling)
.wrangler/

packaging/dist/
/dist/
target-debian/
Loading
Loading