name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
jobs:
build:
name: ${{ matrix.name }}
strategy:
fail-fast: false
matrix:
include:
- name: Linux x86_64 (tar.gz)
target: x86_64-unknown-linux-gnu
format: tar-gz
- name: Linux x86_64 (deb)
target: x86_64-unknown-linux-gnu
format: deb
deps: rpm
- name: Linux x86_64 (rpm)
target: x86_64-unknown-linux-gnu
format: rpm
deps: rpm
- name: Arch Linux x86_64
target: x86_64-unknown-linux-gnu
format: arch
- name: Linux x86_64 (musl)
target: x86_64-unknown-linux-musl
format: musl-tar-gz
deps: musl-tools
- name: Linux ARM64 (tar.gz)
target: aarch64-unknown-linux-gnu
format: tar-gz
deps: gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
- name: Linux ARM64 (deb)
target: aarch64-unknown-linux-gnu
format: deb
deps: gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu rpm
- name: Linux ARM64 (rpm)
target: aarch64-unknown-linux-gnu
format: rpm
deps: gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu rpm
- name: Arch Linux ARM64
target: aarch64-unknown-linux-gnu
format: arch-arm64
deps: gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
- name: Linux ARM64 (musl)
target: aarch64-unknown-linux-musl
format: musl-tar-gz
deps: musl-tools gcc-aarch64-linux-gnu
- name: Windows x86_64 (zip)
target: x86_64-pc-windows-gnu
format: zip
deps: gcc-mingw-w64-x86-64
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v7
- name: Extract tag name
run: echo "VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- uses: dtolnay/rust-toolchain@stable
- name: Install target
run: rustup target add ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install system dependencies
if: matrix.deps != ''
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq ${{ matrix.deps }}
- name: Install packaging tools
if: matrix.format == 'deb' || matrix.format == 'rpm'
run: |
cargo install cargo-deb --locked
cargo install cargo-rpm --locked
- name: Build and package
shell: bash
run: |
set -euxo pipefail
mkdir -p dist
case "${{ matrix.format }}" in
tar-gz)
cargo build --release --target ${{ matrix.target }}
cp target/${{ matrix.target }}/release/leenfetch dist/leenfetch
tar -czf "dist/leenfetch-${VERSION}-linux-${{ matrix.target == 'x86_64-unknown-linux-gnu' && 'x86_64' || 'aarch64' }}.tar.gz" -C dist leenfetch
rm dist/leenfetch
;;
deb)
cargo build --release --target ${{ matrix.target }}
cargo deb ${{ matrix.target == 'aarch64-unknown-linux-gnu' && '--no-strip ' || '' }}--target ${{ matrix.target }}
cp target/${{ matrix.target }}/debian/*.deb "dist/leenfetch-${VERSION}-debian-${{ matrix.target == 'x86_64-unknown-linux-gnu' && 'x86_64' || 'aarch64' }}.deb"
;;
rpm)
cargo build --release --target ${{ matrix.target }}
case "${{ matrix.target }}" in
x86_64-unknown-linux-gnu)
cargo rpm init 2>/dev/null || true
cargo rpm build 2>/dev/null || true
find target/release/rpmbuild -name "*.rpm" -exec cp {} "dist/leenfetch-${VERSION}-rhel-x86_64.rpm" \; 2>/dev/null || true
;;
aarch64-unknown-linux-gnu)
{
echo "Name: leenfetch"
echo "Version: ${VERSION#v}"
echo "Release: 1%{?dist}"
echo "Summary: Fast, minimal system info tool"
echo "License: MIT"
echo "BuildArch: aarch64"
echo ""
echo "%description"
echo "Fast and customizable system info tool for the terminal."
echo ""
echo "%install"
echo "install -Dm0755 %{_sourcedir}/leenfetch %{buildroot}%{_bindir}/leenfetch"
echo ""
echo "%files"
echo "%{_bindir}/leenfetch"
} > dist/leenfetch.spec
cp target/${{ matrix.target }}/release/leenfetch dist/leenfetch
rpmbuild -bb dist/leenfetch.spec \
--define "_sourcedir $PWD/dist" \
--define "_rpmdir $PWD/dist" \
--define "_target_cpu aarch64" \
--nodeps 2>/dev/null || true
for f in $(find dist -name "*.rpm" -type f 2>/dev/null); do
mv "$f" "dist/leenfetch-${VERSION}-rhel-aarch64.rpm" 2>/dev/null || true
done
rm -f dist/leenfetch dist/leenfetch.spec
;;
esac
;;
arch)
cargo build --release --target ${{ matrix.target }}
docker run --rm -v $PWD:/work archlinux:latest bash -c "
pacman -Sy --noconfirm base-devel
cp /work/target/${{ matrix.target }}/release/leenfetch /work/
cd /work
useradd build
chown build:build leenfetch PKGBUILD
su build -c 'makepkg -f' || true
cp *.pkg.tar.zst /work/dist/ 2>/dev/null || true
" || true
if [ -f dist/*.pkg.tar.zst ]; then
mv dist/*.pkg.tar.zst "dist/leenfetch-${VERSION}-arch-x86_64.pkg.tar.zst"
else
BIN=target/${{ matrix.target }}/release/leenfetch
mkdir -p pkg/usr/bin
cp "$BIN" pkg/usr/bin/leenfetch
printf 'pkgname = leenfetch\npkgver = %s\npkgdesc = Fast, minimal system info tool\nurl = https://github.com/drunkleen/leenfetch\nbuilddate = %d\npackager = DrunkLeen\nsize = %d\narch = x86_64\nlicense = MIT\n' \
"${VERSION#v}" "$(date +%s)" "$(stat -c%s "$BIN")" > .PKGINFO
tar -c --zstd -f "dist/leenfetch-${VERSION}-arch-x86_64.pkg.tar.zst" .PKGINFO -C pkg . 2>/dev/null || true
rm -rf pkg .PKGINFO
fi
;;
arch-arm64)
cargo build --release --target ${{ matrix.target }}
BIN=target/${{ matrix.target }}/release/leenfetch
mkdir -p pkg/usr/bin
cp "$BIN" pkg/usr/bin/leenfetch
printf 'pkgname = leenfetch\npkgver = %s\npkgdesc = Fast, minimal system info tool\nurl = https://github.com/drunkleen/leenfetch\nbuilddate = %d\npackager = DrunkLeen\nsize = %d\narch = aarch64\nlicense = MIT\n' \
"${VERSION#v}" "$(date +%s)" "$(stat -c%s "$BIN")" > .PKGINFO
tar -c --zstd -f "dist/leenfetch-${VERSION}-arch-aarch64.pkg.tar.zst" .PKGINFO -C pkg . 2>/dev/null || true
rm -rf pkg .PKGINFO
;;
musl-tar-gz)
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-gnu-gcc \
cargo build --release --target ${{ matrix.target }}
cp target/${{ matrix.target }}/release/leenfetch dist/leenfetch
tar -czf "dist/leenfetch-${VERSION}-linux-${{ matrix.target == 'x86_64-unknown-linux-musl' && 'x86_64' || 'aarch64' }}-musl.tar.gz" -C dist leenfetch
rm dist/leenfetch
;;
zip)
cargo build --release --target ${{ matrix.target }}
cp target/${{ matrix.target }}/release/leenfetch.exe dist/leenfetch.exe
zip -j "dist/leenfetch-${VERSION}-windows-x86_64.zip" dist/leenfetch.exe
rm dist/leenfetch.exe
;;
esac
- uses: actions/upload-artifact@v7
with:
name: ${{ matrix.name }}
path: dist/*
aur-publish:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Extract version
run: echo "VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Compute source checksum
run: |
curl -sL "https://github.com/${{ github.repository }}/archive/refs/tags/${VERSION}.tar.gz" -o source.tar.gz
echo "SHA256=$(sha256sum source.tar.gz | cut -d' ' -f1)" >> $GITHUB_ENV
- name: Set up SSH key for AUR
run: |
mkdir -p ~/.ssh
echo "${{ secrets.AUR_SECRET }}" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null
cat >> ~/.ssh/config << 'EOF'
Host aur.archlinux.org
IdentityFile ~/.ssh/aur
User aur
EOF
- name: Update AUR PKGBUILD and push
run: |
git clone ssh://aur@aur.archlinux.org/leenfetch.git aur-repo
cd aur-repo
git config user.name "DrunkLeen"
git config user.email "snape@drunkleen.com"
sed -i "s/^pkgver=.*/pkgver=${VERSION#v}/" PKGBUILD
sed -i "s/^sha256sums=.*/sha256sums=('${SHA256}')/" PKGBUILD
docker run --rm -v $PWD:/work archlinux:latest bash -c "
pacman -Sy --noconfirm base-devel
cd /work
useradd build
chown build:build /work PKGBUILD
su build -c 'makepkg --printsrcinfo' > .SRCINFO.tmp
[ -s .SRCINFO.tmp ] || { echo '.SRCINFO is empty - makepkg failed'; exit 1; }
mv .SRCINFO.tmp .SRCINFO
"
git add PKGBUILD .SRCINFO
git commit -m "Update to ${VERSION}"
git push origin master
release:
needs: aur-publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Extract tag name
run: echo "VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- uses: actions/download-artifact@v8
with:
path: dist
- name: Flatten downloaded artifacts
run: |
find dist -mindepth 2 -type f -exec mv -f {} dist/ \;
find dist -mindepth 1 -type d -empty -delete
- name: Generate checksums
run: |
cd dist
find . -type f ! -name "SHA256SUMS.txt" -print0 | xargs -0 sha256sum > SHA256SUMS.txt
- name: Build release notes body
env:
REPO: ${{ github.repository }}
run: |
set -euxo pipefail
VERSION_NUM=${VERSION#v}
sed -n "/^## \[${VERSION_NUM}\]/,/^## \[/p" CHANGELOG.md | head -n -2 > dist/CHANGELOG_SECTION.md
{
echo "# 🐧 LeenFetch ${VERSION}"
echo ""
echo "## Changelog"
echo ""
cat dist/CHANGELOG_SECTION.md
echo ""
echo "---"
echo ""
echo "## 📦 Available Downloads"
echo ""
echo "| File | Platform | Arch |"
echo "|------|----------|------|"
echo "| [leenfetch-${VERSION}-arch-x86_64.pkg.tar.zst](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-arch-x86_64.pkg.tar.zst) | Arch Linux | x86_64 |"
echo "| [leenfetch-${VERSION}-arch-aarch64.pkg.tar.zst](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-arch-aarch64.pkg.tar.zst) | Arch Linux | ARM64 |"
echo "| [leenfetch-${VERSION}-debian-x86_64.deb](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-debian-x86_64.deb) | Debian/Ubuntu | x86_64 |"
echo "| [leenfetch-${VERSION}-debian-aarch64.deb](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-debian-aarch64.deb) | Debian/Ubuntu | ARM64 |"
echo "| [leenfetch-${VERSION}-rhel-x86_64.rpm](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-rhel-x86_64.rpm) | RHEL/Fedora | x86_64 |"
if [ -f "dist/leenfetch-${VERSION}-rhel-aarch64.rpm" ]; then
echo "| [leenfetch-${VERSION}-rhel-aarch64.rpm](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-rhel-aarch64.rpm) | RHEL/Fedora | ARM64 |"
fi
echo "| [leenfetch-${VERSION}-linux-x86_64.tar.gz](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-linux-x86_64.tar.gz) | Linux (tar.gz) | x86_64 |"
echo "| [leenfetch-${VERSION}-linux-aarch64.tar.gz](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-linux-aarch64.tar.gz) | Linux (tar.gz) | ARM64 |"
echo "| [leenfetch-${VERSION}-linux-x86_64-musl.tar.gz](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-linux-x86_64-musl.tar.gz) | Linux (musl, static) | x86_64 |"
if [ -f "dist/leenfetch-${VERSION}-linux-aarch64-musl.tar.gz" ]; then
echo "| [leenfetch-${VERSION}-linux-aarch64-musl.tar.gz](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-linux-aarch64-musl.tar.gz) | Linux (musl, static) | ARM64 |"
fi
echo "| [leenfetch-${VERSION}-windows-x86_64.zip](https://github.com/drunkleen/leenfetch/releases/download/${VERSION}/leenfetch-${VERSION}-windows-x86_64.zip) | Windows | x86_64 |"
echo ""
echo "## Checksums"
echo '```'
} > dist/RELEASE.md
cat dist/SHA256SUMS.txt >> dist/RELEASE.md
echo '```' >> dist/RELEASE.md
rm -f dist/CHANGELOG_SECTION.md
- name: Append generated release notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
set -euxo pipefail
if gh api -X POST repos/$REPO/releases/generate-notes -f tag_name=${VERSION} --jq '.body' > /tmp/notes.md 2>/dev/null; then
{
cat dist/RELEASE.md
echo
echo "## Changes & Commits"
echo
cat /tmp/notes.md
} > dist/RELEASE_NOTES.md
mv dist/RELEASE_NOTES.md dist/RELEASE.md
fi
- name: Upload Release Assets
uses: softprops/action-gh-release@v2
with:
files: dist/*
generate_release_notes: false
body_path: dist/RELEASE.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}