Files
plezy/.github/workflows/windows-gitea-release.yml
T
Yorick Rommers eddbb236fe
Mirror release tags to GitHub build bridge / Mirror tag to GitHub (push) Successful in 18s
ci: gate optional release steps on env vars, not the secrets context
GitHub Actions rejects the secrets context in if: conditions; the
workflow failed validation on push. Mirror build.yml's pattern of
copying the secret into step env and gating on that.
2026-08-12 01:18:53 +02:00

205 lines
8.7 KiB
YAML

name: Publish Windows Release to Gitea
# Builds the Windows release on GitHub-hosted runners and publishes it to the
# release of the matching tag in the Gitea repository. It is triggered by tags
# mirrored from Gitea by .gitea/workflows/windows-release.yml (or by any tag
# pushed to this fork directly).
#
# This workflow is skipped everywhere except GitHub and except the
# yorickr/plezy fork, which owns the GITEA_TOKEN secret. It never creates a
# GitHub release; the Gitea release is the artifact channel.
on:
push:
tags:
- "*"
env:
# Only place this workflow names the SDK; .github/actions/setup-flutter-git pins the same release.
FLUTTER_VERSION: "3.44.0"
# Same defines as build.yml, except Sentry is always enabled: these builds are
# the primary channel from the Gitea repo, and the DSN is compiled in anyway.
RELEASE_DART_DEFINES: >-
--dart-define=ENABLE_UPDATE_CHECK=true
--dart-define=ENABLE_SENTRY=true
--dart-define=GIT_COMMIT=${{ github.sha }}
--dart-define=SENTRY_ENVIRONMENT=gitea-release
--dart-define=ENABLE_DONATIONS=true
jobs:
build-windows:
name: Build Windows x64 and publish to Gitea
# Never queue on the Gitea instance (it has no Windows runner) and never
# run in random forks (they lack GITEA_TOKEN).
if: github.server_url == 'https://github.com' && github.repository == 'yorickr/plezy'
runs-on: windows-latest
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- name: Setup Flutter
uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 # v2
with:
channel: "stable"
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true
cache-key: "gitea-release-flutter-:os:-:channel:-:version:-:arch:-:hash:"
pub-cache: false
- name: Cache Pub dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: |
~\AppData\Local\Pub\Cache
key: gitea-release-${{ runner.os }}-${{ runner.arch }}-pub-${{ hashFiles('pubspec.yaml', 'pubspec.lock') }}
- name: Install dependencies
shell: pwsh
run: flutter pub get --enforce-lockfile --no-example
- name: Install patched Flutter engine (DComp)
shell: pwsh
run: |
flutter precache --windows
.\windows\tool\install-patched-engine.ps1
- name: Build Windows x64
shell: pwsh
run: flutter build windows --release ${{ env.RELEASE_DART_DEFINES }} --dart-define=SENTRY_DIST=gitea-windows-x64 --split-debug-info=debug-info/windows-x64
- name: Upload symbols to bugs.plezy.app
# Only when this fork has been given the admin token (the production
# token lives on edde746/plezy, which is not the build bridge).
# The secrets context is unavailable in `if`, so gate on the env copy.
if: env.BUGS_ADMIN_TOKEN != ''
shell: pwsh
env:
BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }}
SENTRY_DIST: gitea-windows-x64
run: .\scripts\upload-symbols.ps1 windows-x64
- name: Read version from pubspec
id: version
shell: pwsh
run: |
$v = (Select-String -Path pubspec.yaml -Pattern '^version:\s*(\S+)').Matches[0].Groups[1].Value -replace '\+.*'
echo "version=$v" >> $env:GITHUB_OUTPUT
- name: Build installer and portable
shell: pwsh
run: .\windows\build-installer.ps1 -X64BuildDir "build\windows\x64\runner\Release" -Version "${{ steps.version.outputs.version }}"
- name: Sign installer for WinSparkle (EdDSA)
if: env.SPARKLE_PRIVATE_KEY != ''
env:
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
shell: pwsh
run: |
$keyPath = Join-Path $env:RUNNER_TEMP "plezy-winsparkle-ed25519.pem"
try {
Set-Content -Path $keyPath -Value $env:SPARKLE_PRIVATE_KEY -Encoding ascii -NoNewline
$output = & dart run auto_updater:sign_update plezy-windows-installer.exe $keyPath
if ($LASTEXITCODE -ne 0) {
throw "WinSparkle signer failed with exit code $LASTEXITCODE"
}
$match = [regex]::Match($output, 'edSignature="([^"]*)"')
if (-not $match.Success) {
throw "WinSparkle signer returned no EdDSA signature"
}
Set-Content -Path win-ed-signature.txt -Value $match.Groups[1].Value -Encoding ascii -NoNewline
Set-Content -Path win-installer-size.txt -Value (Get-Item plezy-windows-installer.exe).Length.ToString() -Encoding ascii -NoNewline
} finally {
Remove-Item -Path $keyPath -Force -ErrorAction SilentlyContinue
}
- name: Publish to Gitea release
shell: bash
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GITEA_SERVER: ${{ vars.GITEA_SERVER || 'https://git.yorickrommers.nl' }}
GITEA_REPO: ${{ vars.GITEA_REPO || 'yorickr/plezy' }}
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
if [[ -z "${GITEA_TOKEN}" ]]; then
echo "Missing GITEA_TOKEN secret - cannot publish" >&2
exit 1
fi
API="${GITEA_SERVER}/api/v1/repos/${GITEA_REPO}"
VERSION="${{ steps.version.outputs.version }}"
# Only publish tags that exist in the Gitea repo (i.e. tags mirrored
# from there, or pushed to Gitea directly). Tags that only exist on
# GitHub are not this pipeline's business.
if ! curl -fsS -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/git/refs/tags/${TAG}" >/dev/null 2>&1; then
echo "Tag ${TAG} does not exist in ${GITEA_REPO} on ${GITEA_SERVER}; skipping publish"
exit 0
fi
NOTES=$(cat <<'EOF'
Windows build for Plezy.
Artifacts:
- **plezy-windows-installer.exe** - Inno Setup installer (silent-update compatible, auto-detects architecture)
- **plezy-windows-x64-portable.7z** - portable x64 build (no installation needed)
Built automatically on GitHub-hosted runners from this tag and published to
this Gitea release.
EOF
)
if RELEASE=$(curl -fsS -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/releases/tags/${TAG}" 2>/dev/null); then
RELEASE_ID=$(echo "${RELEASE}" | jq -r '.id')
echo "Release for ${TAG} already exists (id ${RELEASE_ID}); updating"
BODY=$(jq -n --arg name "Plezy ${VERSION}" --arg body "${NOTES}" \
'{name: $name, body: $body, draft: false, prerelease: false}')
RESP=$(curl -fsS -X PATCH -H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" -d "${BODY}" \
"${API}/releases/${RELEASE_ID}")
else
echo "Creating release for ${TAG}"
BODY=$(jq -n --arg tag "${TAG}" --arg name "Plezy ${VERSION}" --arg body "${NOTES}" \
'{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}')
RESP=$(curl -fsS -X POST -H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" -d "${BODY}" \
"${API}/releases")
fi
RELEASE_ID=$(echo "${RESP}" | jq -r '.id')
if [[ -z "${RELEASE_ID}" || "${RELEASE_ID}" == "null" ]]; then
echo "Failed to create/update the release:" >&2
echo "${RESP}" >&2
exit 1
fi
# Upload each asset, replacing a same-named asset from an earlier run.
upload() {
local FILE="$1"
local NAME
NAME=$(basename "${FILE}")
local EXISTING_ASSET
EXISTING_ASSET=$(curl -fsS -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/releases/${RELEASE_ID}/assets" | jq -r --arg name "${NAME}" \
'.[] | select(.name == $name) | .id')
if [[ -n "${EXISTING_ASSET}" ]]; then
curl -fsS -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/releases/${RELEASE_ID}/assets/${EXISTING_ASSET}" >/dev/null
fi
curl -fsS -X POST -H "Authorization: token ${GITEA_TOKEN}" \
-F "attachment=@${FILE}" \
"${API}/releases/${RELEASE_ID}/assets?name=${NAME}" >/dev/null
echo "Uploaded ${NAME} ($(stat -c%s "${FILE}") bytes)"
}
upload plezy-windows-x64-portable.7z
upload plezy-windows-installer.exe
echo "Published release for ${TAG}: ${GITEA_SERVER}/${GITEA_REPO}/releases/tag/${TAG}"