5e7b5d0d13
xvfb-run wraps wine in a fake X display, but it shells out to xauth to set up the cookie. xauth isn't part of the xvfb package on Debian trixie. Add it explicitly. Failure: 'xvfb-run: error: xauth command not found' (run #7, task 8). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
199 lines
8.8 KiB
YAML
199 lines
8.8 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
# We only ever publish a tag once. Don't cancel a running release —
|
|
# if the user re-pushed the same tag, that's a manual action and
|
|
# should fail loudly via Forgejo's "release exists" 409 from the API.
|
|
concurrency:
|
|
group: release-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: go
|
|
steps:
|
|
- name: Checkout
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
git clone --no-checkout "https://x-access-token:${GITHUB_TOKEN}@git.okcu.io/${GITHUB_REPOSITORY}.git" /tmp/src
|
|
git -C /tmp/src checkout "$GITHUB_SHA"
|
|
cp -a /tmp/src/. .
|
|
|
|
- name: Extract version from tag
|
|
id: version
|
|
run: |
|
|
TAG="${GITHUB_REF#refs/tags/}"
|
|
VERSION="${TAG#v}"
|
|
echo "tag=${TAG}" | tee -a "$GITHUB_OUTPUT"
|
|
echo "version=${VERSION}" | tee -a "$GITHUB_OUTPUT"
|
|
|
|
- name: Cross-compile drover.exe (windows/amd64)
|
|
env:
|
|
GOOS: windows
|
|
GOARCH: amd64
|
|
CGO_ENABLED: '0'
|
|
run: |
|
|
set -e
|
|
BUILD_DATE="$(date -u +%Y-%m-%d)"
|
|
SHORT_SHA="${GITHUB_SHA:0:7}"
|
|
mkdir -p dist
|
|
go build -trimpath -ldflags="-s -w \
|
|
-X main.Version=${{ steps.version.outputs.version }} \
|
|
-X main.Commit=${SHORT_SHA} \
|
|
-X main.BuildDate=${BUILD_DATE}" \
|
|
-o "dist/drover-${{ steps.version.outputs.tag }}-windows-amd64.exe" \
|
|
./cmd/drover
|
|
|
|
- name: Build portable zip
|
|
run: |
|
|
set -e
|
|
# Stage files for the zip in a clean directory so the archive root
|
|
# contains exactly what users see when they unpack.
|
|
apt-get update >/dev/null
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends zip >/dev/null
|
|
STAGE="$(mktemp -d)"
|
|
cp "dist/drover-${{ steps.version.outputs.tag }}-windows-amd64.exe" "$STAGE/drover.exe"
|
|
mkdir -p "$STAGE/windivert"
|
|
cp third_party/windivert/WinDivert.dll "$STAGE/windivert/"
|
|
cp third_party/windivert/WinDivert64.sys "$STAGE/windivert/"
|
|
cp third_party/windivert/LICENSE-LGPL "$STAGE/windivert/"
|
|
cp third_party/windivert/README.md "$STAGE/windivert/"
|
|
cp LICENSE "$STAGE/LICENSE.txt"
|
|
cp README.md "$STAGE/README.md"
|
|
# zip from inside STAGE so paths are relative
|
|
( cd "$STAGE" && zip -r9 - . ) > "dist/drover-${{ steps.version.outputs.tag }}-windows-amd64.zip"
|
|
|
|
- name: Install Wine + Inno Setup (via innoextract, no Wine GUI install)
|
|
run: |
|
|
set -e
|
|
dpkg --add-architecture i386
|
|
apt-get update
|
|
# innoextract unpacks Inno Setup .exe installers without running them
|
|
# under Wine. We then copy the extracted compiler files into the Wine
|
|
# prefix and call ISCC.exe via Wine — much more reliable than running
|
|
# the whole interactive installer through Wine + Xvfb (which failed
|
|
# silently in the previous iteration).
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
wine wine64 innoextract xvfb xauth curl ca-certificates \
|
|
>/dev/null
|
|
export WINEPREFIX="$HOME/.wine"
|
|
export WINEDLLOVERRIDES="mscoree,mshtml="
|
|
export DISPLAY=":99"
|
|
Xvfb :99 -screen 0 1024x768x16 &
|
|
sleep 1
|
|
wineboot --init >/dev/null 2>&1 || true
|
|
# Pin Inno Setup version. The innoextract package in Debian
|
|
# trixie (1.9.x) parses headers up through Inno Setup 6.2.x.
|
|
# 6.3+ already fails with "Unexpected setup data version" /
|
|
# "Stream error while parsing setup headers", 6.5+ with
|
|
# "Setup loader checksum mismatch". Stay on 6.2.2 until either
|
|
# innoextract gets bumped in Debian or we replace it with a
|
|
# docker-image-based ISCC step.
|
|
INNO_VERSION="6.2.2"
|
|
INNO_TAG="is-6_2_2"
|
|
curl -fsSL -o /tmp/innosetup.exe \
|
|
"https://github.com/jrsoftware/issrc/releases/download/${INNO_TAG}/innosetup-${INNO_VERSION}.exe"
|
|
# innoextract unpacks the installer payload to ./app — that's the
|
|
# full Inno Setup directory tree (ISCC.exe + support DLLs/scripts).
|
|
mkdir -p /tmp/inno-extract
|
|
( cd /tmp/inno-extract && innoextract /tmp/innosetup.exe )
|
|
# Place it where Windows-style paths can resolve. Wine maps
|
|
# C:\InnoSetup to ~/.wine/drive_c/InnoSetup so we copy there.
|
|
mkdir -p "$HOME/.wine/drive_c/InnoSetup"
|
|
cp -a /tmp/inno-extract/app/. "$HOME/.wine/drive_c/InnoSetup/"
|
|
# Sanity check
|
|
ls -la "$HOME/.wine/drive_c/InnoSetup/ISCC.exe"
|
|
xvfb-run -a wine "C:\\InnoSetup\\ISCC.exe" /? 2>&1 | head -5 || true
|
|
|
|
- name: Compile Inno Setup installer
|
|
env:
|
|
DISPLAY: ":99"
|
|
WINEDLLOVERRIDES: "mscoree,mshtml="
|
|
run: |
|
|
set -e
|
|
export WINEPREFIX="$HOME/.wine"
|
|
# installer.iss references "..\drover.exe" relative to installer/,
|
|
# i.e. expects a plain drover.exe at repo root. Stage a copy of the
|
|
# versioned binary there before invoking ISCC.
|
|
cp "dist/drover-${{ steps.version.outputs.tag }}-windows-amd64.exe" drover.exe
|
|
# Inno Setup wants Windows-style /D defines and the script path
|
|
# in DOS form. We invoke from repo root; iss script resolves its
|
|
# own ..\ paths from installer/.
|
|
mkdir -p installer/Output
|
|
xvfb-run -a wine "C:\\InnoSetup\\ISCC.exe" \
|
|
"/DMyAppVersion=${{ steps.version.outputs.version }}" \
|
|
"installer\\installer.iss"
|
|
# Inno Setup default OutputDir is "installer/Output/" (relative
|
|
# to the .iss). Move the produced exe to dist/ with the canonical
|
|
# asset name.
|
|
mv "installer/Output/drover-${{ steps.version.outputs.version }}-setup.exe" \
|
|
"dist/drover-${{ steps.version.outputs.tag }}-setup.exe"
|
|
ls -la dist/
|
|
|
|
- name: Compute SHA256SUMS.txt
|
|
run: |
|
|
set -e
|
|
( cd dist && sha256sum \
|
|
"drover-${{ steps.version.outputs.tag }}-windows-amd64.exe" \
|
|
"drover-${{ steps.version.outputs.tag }}-windows-amd64.zip" \
|
|
"drover-${{ steps.version.outputs.tag }}-setup.exe" \
|
|
) > dist/SHA256SUMS.txt
|
|
cat dist/SHA256SUMS.txt
|
|
|
|
- name: Create Forgejo release and upload assets
|
|
env:
|
|
FJ_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
FJ_HOST: git.okcu.io
|
|
FJ_REPO: ${{ github.repository }}
|
|
TAG: ${{ steps.version.outputs.tag }}
|
|
VERSION: ${{ steps.version.outputs.version }}
|
|
run: |
|
|
set -e
|
|
# jq is used to build the JSON body safely. Install if missing.
|
|
command -v jq >/dev/null || {
|
|
apt-get update >/dev/null
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends jq >/dev/null
|
|
}
|
|
# Detect prerelease from tag (anything with a hyphen after the version
|
|
# number, e.g. v0.1.0-rc.1, v0.1.0-beta) is a prerelease.
|
|
PRERELEASE="false"
|
|
case "$VERSION" in
|
|
*-*) PRERELEASE="true" ;;
|
|
esac
|
|
|
|
# 1. Create the release. If a release for this tag already exists,
|
|
# Forgejo returns 409 and we exit non-zero so the user sees the
|
|
# real reason in the log instead of getting silent overwrites.
|
|
BODY=$(jq -n \
|
|
--arg tag "$TAG" \
|
|
--arg name "Drover-Go $TAG" \
|
|
--argjson prerelease "$PRERELEASE" \
|
|
--arg body "Automated release built from commit $GITHUB_SHA. See [docs](https://git.okcu.io/$FJ_REPO/src/tag/$TAG/docs/) for installation and troubleshooting." \
|
|
'{tag_name: $tag, name: $name, prerelease: $prerelease, body: $body, draft: false}')
|
|
RELEASE_JSON=$(curl -fsS -X POST \
|
|
-H "Authorization: token $FJ_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d "$BODY" \
|
|
"https://$FJ_HOST/api/v1/repos/$FJ_REPO/releases")
|
|
RELEASE_ID=$(echo "$RELEASE_JSON" | jq -r '.id')
|
|
echo "Created release id=$RELEASE_ID"
|
|
|
|
# 2. Upload each asset via multipart/form-data
|
|
for asset in dist/*.exe dist/*.zip dist/SHA256SUMS.txt; do
|
|
[ -f "$asset" ] || continue
|
|
name="$(basename "$asset")"
|
|
echo "Uploading $name..."
|
|
curl -fsS -X POST \
|
|
-H "Authorization: token $FJ_TOKEN" \
|
|
-F "attachment=@$asset;filename=$name" \
|
|
"https://$FJ_HOST/api/v1/repos/$FJ_REPO/releases/$RELEASE_ID/assets?name=$name" \
|
|
>/dev/null
|
|
done
|
|
|
|
echo "Release $TAG published with $(ls dist | wc -l) assets."
|