Skip to content

Release

Release #17

Workflow file for this run

name: Publish to crates.io
on:
workflow_dispatch:
jobs:
checks:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.get_tag.outputs.tag }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check HEAD has a tag
id: get_tag
run: |
TAG=$(git tag --points-at HEAD | head -n1)
if [ -z "$TAG" ]; then
echo "Error: HEAD commit has no tag. Please tag this commit before publishing."
exit 1
fi
echo "Found tag: $TAG"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Check tag matches Cargo.toml version
run: |
TAG="${{ steps.get_tag.outputs.tag }}"
# Strip leading 'v' if present (v0.4.1 -> 0.4.1)
VERSION="${TAG#v}"
CARGO_VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
if [ "$VERSION" != "$CARGO_VERSION" ]; then
echo "Error: Tag version ($VERSION) does not match Cargo.toml version ($CARGO_VERSION)"
exit 1
fi
echo "Tag matches Cargo.toml version: $VERSION"
- name: Check version not already on crates.io
run: |
TAG="${{ steps.get_tag.outputs.tag }}"
# Strip leading 'v' if present (v0.4.1 -> 0.4.1)
VERSION="${TAG#v}"
echo "Checking if $VERSION exists on crates.io..."
CRATE_NAME=$(grep -m1 '^name' Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/$CRATE_NAME/$VERSION")
if [ "$HTTP_STATUS" = "200" ]; then
echo "Error: Version $VERSION already exists on crates.io"
exit 1
fi
echo "Version $VERSION not yet published, proceeding."
ci:
needs: checks
uses: ./.github/workflows/ci.yml
publish:
needs: ci
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install packages needed for build
run: sudo apt-get update && sudo apt-get install -y build-essential libgtksourceview-5-dev
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Publish to crates.io
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
appimage:
needs: [checks, publish]
strategy:
matrix:
include:
- runner: ubuntu-24.04
arch: x86_64
- runner: ubuntu-24.04-arm
arch: aarch64
runs-on: ${{ matrix.runner }}
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Install packages needed for build
run: sudo apt-get update && sudo apt-get install -y build-essential libgtksourceview-5-dev librsvg2-bin libfuse2
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Build release binary
run: cargo build --release
- name: Convert SVG icon to PNG
run: rsvg-convert -w 256 -h 256 assets/mergers.svg -o mergers.png
- name: Download appimagetool
run: |
curl -fsSL -o appimagetool https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${{ matrix.arch }}.AppImage
chmod +x appimagetool
- name: Build AppImage
run: |
mkdir -p AppDir/usr/bin
cp target/release/mergers AppDir/usr/bin/mergers
cp assets/mergers.desktop AppDir/mergers.desktop
cp mergers.png AppDir/mergers.png
ln -s usr/bin/mergers AppDir/AppRun
./appimagetool --appimage-extract-and-run AppDir mergers-${{ matrix.arch }}.AppImage
- name: Upload AppImage to GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${{ needs.checks.outputs.tag }}"
gh release create "$TAG" --title "$TAG" --generate-notes 2>/dev/null || true
gh release upload "$TAG" mergers-${{ matrix.arch }}.AppImage --clobber
macos:
needs: [checks, publish]
runs-on: macos-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: brew install gtk4 gtksourceview5
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Build release binary
run: cargo build --release
- name: Create tarball
run: tar -czf mergers-darwin-aarch64.tar.gz -C target/release mergers
- name: Upload to GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${{ needs.checks.outputs.tag }}"
gh release create "$TAG" --title "$TAG" --generate-notes 2>/dev/null || true
gh release upload "$TAG" mergers-darwin-aarch64.tar.gz --clobber
windows:
needs: [checks, publish]
strategy:
fail-fast: false
matrix:
include:
- runner: windows-latest
msystem: UCRT64
package_prefix: mingw-w64-ucrt-x86_64
rust_target: x86_64-pc-windows-gnu
rust_host: x86_64-pc-windows-gnu
arch: x86_64
- runner: windows-latest-arm
msystem: CLANGARM64
package_prefix: mingw-w64-clang-aarch64
rust_target: aarch64-pc-windows-gnu
rust_host: aarch64-pc-windows-gnu
arch: aarch64
runs-on: ${{ matrix.runner }}
permissions:
contents: write
steps:
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
${{ matrix.package_prefix }}-gtk4
${{ matrix.package_prefix }}-gtksourceview5
${{ matrix.package_prefix }}-pkgconf
${{ matrix.package_prefix }}-gcc
- uses: actions/checkout@v6
- name: Install Rust
shell: msys2 {0}
run: |
export CARGO_HOME="$(pwd)/.cargo"
export RUSTUP_HOME="$(pwd)/.rustup"
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-host ${{ matrix.rust_host }} --default-toolchain stable
- name: Build release binary
shell: msys2 {0}
run: |
export PATH="$(pwd)/.cargo/bin:$PATH"
export PKG_CONFIG_ALLOW_CROSS=1
cargo build --release --target ${{ matrix.rust_target }}
- name: Bundle binary with DLLs
shell: msys2 {0}
run: |
mkdir -p dist
cp target/${{ matrix.rust_target }}/release/mergers.exe dist/
# Copy all required DLLs from MSYS2
ldd target/${{ matrix.rust_target }}/release/mergers.exe | grep -i "$MSYSTEM" | awk '{print $3}' | xargs -I{} cp {} dist/
# Copy GtkSourceView language specs and styles
mkdir -p dist/share
cp -r /$MSYSTEM/share/gtksourceview-5 dist/share/gtksourceview-5
# Copy GTK schema files
mkdir -p dist/share/glib-2.0/schemas
cp /$MSYSTEM/share/glib-2.0/schemas/gschemas.compiled dist/share/glib-2.0/schemas/
# Copy icon theme
mkdir -p dist/share/icons
cp -r /$MSYSTEM/share/icons/hicolor dist/share/icons/
cp -r /$MSYSTEM/share/icons/Adwaita dist/share/icons/ 2>/dev/null || true
- name: Create zip
shell: msys2 {0}
run: |
cd dist
7z a ../mergers-windows-${{ matrix.arch }}.zip ./*
- name: Upload to GitHub release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="${{ needs.checks.outputs.tag }}"
gh release create "$TAG" --title "$TAG" --generate-notes 2>/dev/null || true
gh release upload "$TAG" mergers-windows-${{ matrix.arch }}.zip --clobber
homebrew:
needs: [checks, macos]
runs-on: ubuntu-latest
steps:
- name: Determine version
id: version
run: |
TAG="${{ needs.checks.outputs.tag }}"
VERSION="${TAG#v}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Compute SHA256 checksum
id: sha
run: |
TAG="${{ steps.version.outputs.tag }}"
URL="https://github.com/joske/mergers/releases/download/${TAG}/mergers-darwin-aarch64.tar.gz"
SHA=$(curl -sL "$URL" | shasum -a 256 | cut -d' ' -f1)
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
- name: Checkout tap repository
uses: actions/checkout@v6
with:
repository: joske/homebrew-mergers
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
- name: Update formula
env:
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
SHA: ${{ steps.sha.outputs.sha }}
run: |
cat > Formula/mergers.rb << EOF
class Mergers < Formula
desc "Visual diff and merge tool written in Rust with GTK4"
homepage "https://github.com/joske/mergers"
version "${VERSION}"
license "GPL-2.0-only"
url "https://github.com/joske/mergers/releases/download/${TAG}/mergers-darwin-aarch64.tar.gz"
sha256 "${SHA}"
depends_on :macos
depends_on "gtk4"
depends_on "gtksourceview5"
def install
bin.install "mergers"
end
test do
assert_match version.to_s, shell_output("\#{bin}/mergers --version")
end
end
EOF
- name: Commit and push
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/mergers.rb
git commit -m "Update mergers to ${{ steps.version.outputs.tag }}"
git push