Files
Motionity/.gitea/workflows/release.yml
T
kawaandClaude Sonnet 5 52eb14b3c8 fix: Wine locale crash and rename secrets off the GITEA_ prefix
C.UTF-8 for the win/AppImage build step: Wine's makensis was aborting
with ERR_ELECTRON_BUILDER_CANNOT_EXECUTE / "main argv conversion
failed!" under the runner's default C/POSIX locale.

Gitea rejects secret names starting with GITEA, so the registry/API
credentials are now BUILD_USER/BUILD_TOKEN.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-28 15:12:08 +02:00

172 lines
7.0 KiB
YAML

name: Release
# Builds the Docker image, the Windows installers (NSIS + portable) and the Linux
# AppImage, then publishes all of it: the image goes to the Gitea container
# registry as `latest` + the tag, the installers are attached to a Gitea release
# for that tag. Flatpak is intentionally not built here — flatpak-builder's
# sandbox (bwrap) needs working user namespaces, which a containerized Actions
# runner is not guaranteed to have; it stays a local-only step via
# scripts/publish.ps1.
#
# There is no Windows runner in this setup, so the "win" target (NSIS + portable)
# is cross-built on the Linux runner via Wine, the same path
# scripts/build-release.ps1 uses for -UseWsl. Unsigned either way.
#
# Requires two Actions secrets on this repo (Settings > Actions > Secrets), a
# token with package read/write *and* repository write (write:repository) scope:
# BUILD_USER - registry/API username
# BUILD_TOKEN - registry/API token
# (named BUILD_* rather than GITEA_* because Gitea rejects secrets whose name
# starts with GITEA)
on:
push:
tags:
- '*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to publish (e.g. v1.2.3)'
required: true
type: string
env:
IMAGE: git.azuze.fr/kawa/motionity
jobs:
release:
runs-on: docker-build
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full tag history, for the changelog compare link
- name: Resolve tag
id: vars
env:
EVENT_NAME: ${{ github.event_name }}
DISPATCH_TAG: ${{ inputs.tag }}
REF_TAG: ${{ github.ref_name }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
echo "tag=$DISPATCH_TAG" >> "$GITHUB_OUTPUT"
else
echo "tag=$REF_TAG" >> "$GITHUB_OUTPUT"
fi
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install build tools (jq, Wine for the NSIS uninstaller)
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y jq wine
- name: Ensure PowerShell
# Debian ships no snapd by default, so this pulls Microsoft's portable
# linux-x64 tarball instead — no package repo or GPG key setup needed.
# A no-op on repeat runs once it's on PATH, since this runner is a
# persistent host, not a fresh container per job.
run: |
if command -v pwsh >/dev/null; then exit 0; fi
url=$(curl -sL https://api.github.com/repos/PowerShell/PowerShell/releases/latest \
| jq -r '.assets[] | select(.name | test("linux-x64\\.tar\\.gz$")) | .browser_download_url')
[ -n "$url" ] || { echo "could not resolve a PowerShell linux-x64 release asset" >&2; exit 1; }
sudo mkdir -p /opt/microsoft/powershell/7
curl -sL "$url" | sudo tar xz -C /opt/microsoft/powershell/7
sudo ln -sf /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh
sudo chmod +x /opt/microsoft/powershell/7/pwsh
- name: Build Windows installers + Linux AppImage
shell: pwsh
env:
TAG: ${{ steps.vars.outputs.tag }}
# Wine's argv conversion aborts with ERR_ELECTRON_BUILDER_CANNOT_EXECUTE
# / "main argv conversion failed!" under the C/POSIX locale that a
# minimal Debian box defaults to. C.UTF-8 is a glibc built-in, no
# locale-gen needed.
LANG: C.UTF-8
LC_ALL: C.UTF-8
run: ./scripts/build-release.ps1 -Targets win,linux-appimage -Tag $env:TAG
- name: Log in to git.azuze.fr
uses: docker/login-action@v3
with:
registry: git.azuze.fr
username: ${{ secrets.BUILD_USER }}
password: ${{ secrets.BUILD_TOKEN }}
- uses: docker/setup-buildx-action@v3
- name: Build and push image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
${{ env.IMAGE }}:latest
${{ env.IMAGE }}:${{ steps.vars.outputs.tag }}
- name: Publish Gitea release
env:
TAG: ${{ steps.vars.outputs.tag }}
GITEA_TOKEN: ${{ secrets.BUILD_TOKEN }}
SERVER_URL: ${{ github.server_url }}
REPO_PATH: ${{ github.repository }}
run: |
set -euo pipefail
api="$SERVER_URL/api/v1/repos/$REPO_PATH/releases"
auth=(-H "Authorization: token $GITEA_TOKEN")
prev_tag=$(git tag --sort=-v:refname | grep -A1 -x -F "$TAG" | tail -n1)
if [ "$prev_tag" = "$TAG" ]; then prev_tag=""; fi
if [ -n "$prev_tag" ]; then
body="**Full Changelog**: $SERVER_URL/$REPO_PATH/compare/$prev_tag...$TAG"
else
body="**Full Changelog**: first release"
fi
echo "changelog: $body"
status=$(curl -s -o /tmp/release.json -w '%{http_code}' "${auth[@]}" "$api/tags/$TAG")
if [ "$status" = "200" ]; then
release_id=$(jq -r '.id' /tmp/release.json)
echo "reusing release $TAG (id $release_id)"
elif [ "$status" = "404" ]; then
echo "creating release $TAG"
payload=$(jq -n --arg tag "$TAG" --arg name "Motionity $TAG" --arg body "$body" \
'{tag_name:$tag, name:$name, body:$body, draft:false}')
status=$(curl -s -o /tmp/release.json -w '%{http_code}' -X POST "${auth[@]}" \
-H "Content-Type: application/json" -d "$payload" "$api")
[ "$status" = "201" ] || { echo "release creation failed ($status):"; cat /tmp/release.json; exit 1; }
release_id=$(jq -r '.id' /tmp/release.json)
else
echo "unexpected status $status fetching release:"; cat /tmp/release.json; exit 1
fi
# Keep the changelog link authoritative even when reusing an existing
# release (a manual re-run after a later tag was pushed).
curl -sf -X PATCH "${auth[@]}" -H "Content-Type: application/json" \
-d "$(jq -n --arg body "$body" '{body:$body}')" \
"$api/$release_id" -o /dev/null
for f in "dist/motionity-$TAG-win-x64-setup.exe" \
"dist/motionity-$TAG-win-x64-portable.exe" \
"dist/motionity-$TAG-linux-x86_64.AppImage" \
"dist/SHA256SUMS.txt"; do
[ -f "$f" ] || { echo "expected artifact missing: $f" >&2; exit 1; }
name=$(basename "$f")
existing_id=$(jq -r --arg n "$name" '.assets[]? | select(.name==$n) | .id' /tmp/release.json)
if [ -n "$existing_id" ]; then
echo "replacing attachment $name (asset $existing_id)"
curl -sf -X DELETE "${auth[@]}" "$api/$release_id/assets/$existing_id" -o /dev/null
else
echo "adding attachment $name"
fi
encoded=$(jq -rn --arg n "$name" '$n|@uri')
curl -sf "${auth[@]}" -F "attachment=@$f" "$api/$release_id/assets?name=$encoded" -o /dev/null
done
echo "release: $SERVER_URL/$REPO_PATH/releases/tag/$TAG"