Files
Craftimizer/.gitea/workflows/release.yml
T
JonKazama-Hellion 960114c142
Security / scan (push) Successful in 17s
Build / Build (Release) (push) Successful in 26s
Release / Build and attach release ZIP (push) Successful in 34s
Force -p:Platform=x64 in workflow dotnet build steps
Project-level dotnet build defaults to AnyCPU and emits to
Craftimizer/bin/Release/, even though the csproj declares
<Platforms>x64</Platforms> and <RuntimeIdentifier>win-x64</RuntimeIdentifier>.
That mismatch silently broke the first v0.1.0 release run
(/JonKazama-Hellion/Craftimizer/actions/runs/387): build succeeded
but 'find Craftimizer/bin/x64/Release -name latest.zip' returned
'No such file or directory' so the release-action got nothing to attach.

Local builds via 'dotnet build Craftimizer.sln' work because solution-
level builds inherit the per-project Platforms list as the default,
which is a different code path from project-level builds.

Add -p:Platform=x64 to both build.yml and release.yml dotnet steps so
the CI build agrees with the find paths in the same workflow.

After this push, the v0.1.0 release can be re-triggered via Gitea's
workflow_dispatch on the tag (Actions UI -> Release -> Run workflow,
pick v0.1.0 from the Ref dropdown). The tag itself stays unchanged.
2026-05-26 20:54:26 +02:00

144 lines
5.2 KiB
YAML

name: Release
# Triggered when a vX.Y.Z tag is pushed. Builds the plugin against the
# current Dalamud staging branch, locates the latest.zip produced by
# DalamudPackager, extracts the matching changelog block from CHANGELOG.md,
# and attaches everything to the Gitea Release.
#
# User-controlled inputs touched by this workflow:
# - the tag name (filtered by on.tags = v*, validated again at runtime
# against ^v\d+\.\d+\.\d+$ before being used in any string)
# All other values are either repo-controlled (paths under
# Craftimizer/bin/x64/Release derived from find) or pinned URLs to goatcorp
# / gitea. Nothing from a webhook event payload (issue/PR titles, commit
# messages, etc.) flows into a run-step.
on:
push:
tags:
- 'v*'
# Manual recovery trigger. Use Gitea's "Run workflow" UI and select the
# tag (e.g. v0.1.0) from the Ref dropdown - not main. The Validate tag
# ref step below hard-fails if a non-tag ref is selected, because
# release-action reads GITHUB_REF directly and rejects anything that
# does not start with refs/tags/.
workflow_dispatch:
permissions:
contents: write
jobs:
release:
name: Build and attach release ZIP
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Validate tag ref
run: |
if [[ "${GITHUB_REF}" != refs/tags/v* ]]; then
echo "::error::Release workflow must run on a v*.X.Y tag ref, got ${GITHUB_REF}"
echo "::error::Push a tag, or pick the tag (not main) in the workflow_dispatch Ref dropdown."
exit 1
fi
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup .NET 10
uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5
with:
dotnet-version: 10.0.x
- name: Download Dalamud staging
run: |
hooks="$HOME/.xlcore/dalamud/Hooks/dev"
mkdir -p "$hooks"
curl -fsSL https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -o dalamud.zip
unzip -oq dalamud.zip -d "$hooks"
- name: Build (Release)
# -p:Platform=x64 is required: csproj declares <Platforms>x64</Platforms>
# and <RuntimeIdentifier>win-x64</RuntimeIdentifier>, but project-level
# dotnet build defaults to AnyCPU and emits to bin/Release/ instead of
# bin/x64/Release/. The Locate latest.zip step below expects the latter.
run: dotnet build Craftimizer/Craftimizer.csproj --configuration Release -p:Platform=x64
- name: Locate latest.zip
id: locate
run: |
zip="$(find Craftimizer/bin/x64/Release -name latest.zip -print -quit)"
if [ -z "$zip" ]; then
echo "latest.zip not found under Craftimizer/bin/x64/Release" >&2
exit 1
fi
echo "Found: $zip"
echo "path=$zip" >> "$GITHUB_OUTPUT"
# Extract the changelog block for the tagged version from CHANGELOG.md.
# Convention: each release block starts with `## vX.Y.Z` and ends at
# the next `## v` or the `---` trailer at the bottom. Fails the
# workflow if no block exists for the tagged version, which is the
# automated counterpart to the "csproj + repo.json + CHANGELOG kept
# in sync" rule.
- name: Generate release body
env:
TAG_NAME: ${{ github.ref_name }}
run: |
set -euo pipefail
tag="$TAG_NAME"
if [[ ! "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Refusing to generate release body for non-semver tag: $tag"
exit 1
fi
version="${tag#v}"
changelog="CHANGELOG.md"
# awk extracts the block starting at "## vX.Y.Z" and stops at the
# next "## v" or the "---" trailer.
block="$(awk -v ver="## v${version}" '
$0 ~ "^"ver" " { take=1; print; next }
take && /^## v[0-9]+\./ { exit }
take && /^---$/ { exit }
take { print }
' "$changelog")"
if [ -z "$block" ]; then
echo "::error::No changelog entry for version $version found in $changelog. Update the changelog before tagging a release."
exit 1
fi
footer=""
if [ -f .gitea/release-footer.md ]; then
footer="$(cat .gitea/release-footer.md)"
fi
{
echo "$block"
echo ""
echo "$footer"
} > release-body.md
echo "Generated release body for $tag:"
echo "----------------------------------------"
cat release-body.md
echo "----------------------------------------"
- name: Expose release body for release-action
id: body
shell: bash
run: |
{
echo 'content<<RELEASE_BODY_EOF'
cat release-body.md
echo 'RELEASE_BODY_EOF'
} >> "$GITHUB_OUTPUT"
- name: Attach to Gitea release
uses: https://gitea.com/actions/release-action@main
with:
files: ${{ steps.locate.outputs.path }}
body: ${{ steps.body.outputs.content }}
api_key: ${{ secrets.GITHUB_TOKEN }}