960114c142
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.
144 lines
5.2 KiB
YAML
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 }}
|