- codeql.yml removed: GitHub-only (uses github/codeql-action/*).
- build.yml + release.yml: runs-on switched to ubuntu-latest (Gitea Cloud
has no Windows runner). Dalamud staging is now downloaded via curl/unzip
into $HOME/.xlcore/dalamud/Hooks/dev/, the path the Dalamud SDK 15 uses
on Linux. Locate-step uses find instead of Get-ChildItem.
- release.yml: softprops/action-gh-release replaced with the Gitea-native
https://gitea.com/actions/release-action. Auto-injected GITHUB_TOKEN on
Gitea Actions has Gitea-API scope and is sufficient.
- forge-announce.yml: environment: Webhook removed (Gitea has no
environments — DISCORD_FORGE_WEBHOOK is a repo-level Actions secret).
avatar_url and embed url switched from raw.githubusercontent.com /
github.com to gitea.com.
- release-footer.md: install URL plus the five doc links (README, PRIVACY,
THIRD_PARTY_NOTICES, SECURITY, SUPPORT) and LICENSE link switched to
gitea.com/.../src/branch/main/. ChatTwo upstream link stays on GitHub.
New workflow: when a vX.Y.Z tag is pushed (or workflow_dispatch
runs with a tag input), reads .github/forge-posts/<tag>.md for the
DE bullet body plus frontmatter (subtitle, versionsnatur), pulls the
matching English block from HellionChat.yaml, builds the Discord
webhook embed and posts it to the Hellion Forge #changelog channel.
Decoupled from release.yml — a fail here doesn't block the release,
and a fail there doesn't block the announce. Hard caps at 5500 chars
total (title + description + footer); major releases that exceed
that get a clear fail message and stay manual.
Tag is read via env: TAG_NAME and validated against ^v\d+\.\d+\.\d+$
before any string interpolation; frontmatter is regex-parsed with
explicit length caps (subtitle 60, versionsnatur 40). Curl posts the
payload via stdin so the secret never appears in process args.
Single retry on transient 5xx after 30s, hard fail on 4xx.