From 4360e452334942a492c9426aaa644c74624735c9 Mon Sep 17 00:00:00 2001 From: randogoth Date: Fri, 9 Oct 2026 07:04:47 +0300 Subject: [PATCH] feat: add windows runner CI and release jobs --- .forgejo/workflows/ci.yml | 27 +++++++++++++++ .forgejo/workflows/release.yml | 63 ++++++++++++++++++++++++++++++++++ windows/bundle.sh | 38 ++++++++++++++++++++ windows/setup.sh | 29 ++-------------- 4 files changed, 131 insertions(+), 26 deletions(-) create mode 100644 windows/bundle.sh diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index cd0dd1a..7a9c576 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -66,3 +66,30 @@ jobs: working-directory: carrier env: GITHUB_TOKEN: "" + + windows: + runs-on: windows-x86_64 + steps: + - uses: https://code.forgejo.org/actions/checkout@v4 + with: + path: carrier + - uses: https://code.forgejo.org/actions/checkout@v4 + with: + repository: randogoth/fumi + ref: main + path: fumi + - uses: https://code.forgejo.org/actions/cache@v4 + with: + path: | + ~/.cargo/registry + carrier/target + fumi/target + key: cargo-windows-${{ hashFiles('carrier/Cargo.lock') }} + restore-keys: cargo-windows- + # No devbox on Windows: the runner host itself is the MSYS2 MINGW64 + # toolchain that windows/setup.sh installs, so this runs the same + # commands devbox's `check` script runs on the other two platforms + # straight from cargo. + - run: cargo fmt --check && cargo build && cargo test + working-directory: carrier + shell: bash diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 90d2cc2..95437b8 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -73,6 +73,69 @@ jobs: "$FORGEJO/api/v1/repos/$REPO/releases/$release_id/assets?name=$NAME" working-directory: carrier + # Same non-gating strategy as the macos job above: this runner is a + # desktop machine that isn't guaranteed to be on when a tag is pushed, + # so it must never gate the release (and must not be gated by it + # either). It builds and bundles via windows/bundle.sh - the same + # script windows/setup.sh runs for local one-command builds - then + # appends the zip to the release the linux+flatpak jobs create, with + # the same poll-for-the-release the macos job does. + windows: + runs-on: windows-x86_64 + steps: + - uses: https://code.forgejo.org/actions/checkout@v4 + with: + path: carrier + - uses: https://code.forgejo.org/actions/checkout@v4 + with: + repository: randogoth/fumi + ref: main + path: fumi + - uses: https://code.forgejo.org/actions/cache@v4 + with: + path: | + ~/.cargo/registry + carrier/target + fumi/target + key: cargo-windows-${{ hashFiles('carrier/Cargo.lock') }} + restore-keys: cargo-windows- + - run: bash windows/bundle.sh + working-directory: carrier + shell: bash + - run: | + REPO="${{ forge.repository }}" + TAG="${{ forge.ref_name }}" + FORGEJO="${{ env.FORGEJO_SERVER_URL }}" + FORGEJO="${FORGEJO%%/}" + TOKEN="${{ forge.token }}" + VERSION=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -1) + FILE="carrier-windows-$VERSION.zip" + NAME="carrier-windows-$VERSION.zip" + + release_id="" + for i in $(seq 1 40); do + body=$(curl --retry 5 -sS -H "Authorization: token $TOKEN" "$FORGEJO/api/v1/repos/$REPO/releases/tags/$TAG") + release_id=$(echo "$body" | grep -o '"id":[0-9]*' | head -1 | grep -o '[0-9]*') + if [ -n "$release_id" ]; then + break + fi + echo "release for $TAG not ready yet, waiting 15s ($i/40)" + sleep 15 + done + + if [ -z "$release_id" ]; then + echo "release for $TAG never appeared after 10 minutes" >&2 + exit 1 + fi + + curl --retry 5 --fail -sS -X POST \ + -H "Authorization: token $TOKEN" \ + -H "Content-Type: multipart/form-data" \ + -F "attachment=@$FILE" \ + "$FORGEJO/api/v1/repos/$REPO/releases/$release_id/assets?name=$NAME" + working-directory: carrier + shell: bash + linux: runs-on: linux-x86_64 steps: diff --git a/windows/bundle.sh b/windows/bundle.sh new file mode 100644 index 0000000..c8ac496 --- /dev/null +++ b/windows/bundle.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Build carrier and bundle the result: carrier.exe plus the GTK runtime +# into dist/, then dist/ into carrier-windows-.zip. +# +# Run from the carrier checkout inside the MSYS2 MINGW64 shell (or with +# the MINGW64 toolchain on PATH — windows/setup.sh installs the deps, +# and the forgejo Windows runner host already carries them). +set -euo pipefail + +say() { printf '\n==> %s\n' "$*"; } +die() { printf '\n!! %s\n' "$*" >&2; exit 1; } + +say "building carrier (release; the first build takes a while)" +cargo build --release --locked || die "cargo build failed" + +say "bundling the runtime" +rm -rf dist +mkdir -p dist/share/glib-2.0/schemas \ + dist/share/icons/hicolor/512x512/apps \ + dist/share/icons/hicolor/256x256/apps \ + dist/share/icons/hicolor/128x128/apps +cp target/release/carrier.exe dist/ +for dll in $(ldd target/release/carrier.exe | awk '/mingw64/ {print $3}'); do + cp "$dll" dist/ || die "copying $dll failed" +done +[ "$(ls dist/*.dll | wc -l)" -gt 0 ] || die "no DLLs collected — ldd found none under /mingw64" +cp /mingw64/share/glib-2.0/schemas/* dist/share/glib-2.0/schemas/ +glib-compile-schemas dist/share/glib-2.0/schemas/ +cp -r /mingw64/share/icons/Adwaita dist/share/icons/ +cp -r /mingw64/share/icons/hicolor dist/share/icons/ +cp data/icons/com.randogoth.carrier.png dist/share/icons/hicolor/512x512/apps/ +cp data/icons/com.randogoth.carrier-256.png dist/share/icons/hicolor/256x256/apps/ +cp data/icons/com.randogoth.carrier-128.png dist/share/icons/hicolor/128x128/apps/ + +say "zipping" +version=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -1) +rm -f "carrier-windows-$version.zip" +(cd dist && zip -qr "../carrier-windows-$version.zip" .) diff --git a/windows/setup.sh b/windows/setup.sh index fa8e780..f6a591d 100755 --- a/windows/setup.sh +++ b/windows/setup.sh @@ -5,6 +5,8 @@ # GTK runtime into dist/ and carrier-windows.zip. # # If MSYS2 updates its own core mid-run the shell may die — just rerun. +# Building and bundling live in windows/bundle.sh, shared with the +# forgejo Windows release job. set -euo pipefail say() { printf '\n==> %s\n' "$*"; } @@ -31,31 +33,6 @@ pacman -S --noconfirm --needed \ pkg-config --exists gtk4 libadwaita-1 \ || die "gtk4/libadwaita invisible to pkg-config — are you in the MINGW64 shell?" -say "building carrier (release; the first build takes a while)" -cargo build --release --locked || die "cargo build failed" - -say "bundling the runtime" -rm -rf dist -mkdir -p dist/share/glib-2.0/schemas \ - dist/share/icons/hicolor/512x512/apps \ - dist/share/icons/hicolor/256x256/apps \ - dist/share/icons/hicolor/128x128/apps -cp target/release/carrier.exe dist/ -for dll in $(ldd target/release/carrier.exe | awk '/mingw64/ {print $3}'); do - cp "$dll" dist/ || die "copying $dll failed" -done -[ "$(ls dist/*.dll | wc -l)" -gt 0 ] || die "no DLLs collected — ldd found none under /mingw64" -cp /mingw64/share/glib-2.0/schemas/* dist/share/glib-2.0/schemas/ -glib-compile-schemas dist/share/glib-2.0/schemas/ -cp -r /mingw64/share/icons/Adwaita dist/share/icons/ -cp -r /mingw64/share/icons/hicolor dist/share/icons/ -cp data/icons/com.randogoth.carrier.png dist/share/icons/hicolor/512x512/apps/ -cp data/icons/com.randogoth.carrier-256.png dist/share/icons/hicolor/256x256/apps/ -cp data/icons/com.randogoth.carrier-128.png dist/share/icons/hicolor/128x128/apps/ - -say "zipping" -version=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -1) -rm -f "carrier-windows-$version.zip" -(cd dist && zip -qr "../carrier-windows-$version.zip" .) +bash windows/bundle.sh say "done — test with ./dist/carrier.exe (SmartScreen may ask once)"