Initial template: release pipeline + PORTING.md + init helper
What lands in any repo created from this template: - .gitea/workflows/release.yml — canonical Gitea-Actions release pipeline (tag-triggered, curl-based publish, per-asset failure tolerance) - tools/build_zip.sh — git-archive per addon folder, multi-addon bundle - tools/init_from_upstream.sh — one-shot squash-import of upstream tree into <AddonFolder>/ at the repo root - PORTING.md — full CoA-compat bug-pattern checklist (Retail-only globals, FileDataIDs, hardcoded class lists, StaticPopup race, .tga textures, Minimap mask, CLEU arg positions, Ace3 sweep, etc.) - README.md — quick-start backport guide - standard .gitignore (incl dist/) + .gitattributes (* -text)
This commit is contained in:
+116
@@ -0,0 +1,116 @@
|
||||
# Porting addons to CoA / Project Ascension 3.3.5
|
||||
|
||||
The CoA Beta client is WoW 3.3.5 with a heavily reworked FrameXML /
|
||||
SharedXML / StaticPopup / Settings system, 21 custom playable classes,
|
||||
and selectively-modern globals (`C_Timer.After`, `C_ClassInfo`). Most
|
||||
upstream retail / Classic / Wrath addons need a small bundle of fixes.
|
||||
This document lists every recurring failure mode we've seen across the
|
||||
existing 25 Exiles forks plus the matching one-paragraph fix.
|
||||
|
||||
Keep this file in your fork until you're done porting; once everything
|
||||
loads cleanly you can leave it as documentation or delete it.
|
||||
|
||||
The canonical / live version of this checklist is at
|
||||
[coa.exil.es/coa/dev/addons](https://coa.exil.es/coa/dev/addons) — if
|
||||
you discover a new failure mode while porting, please add it there.
|
||||
|
||||
## Bug-pattern checklist
|
||||
|
||||
### Retail-only globals are nil
|
||||
`InterfaceOptionsFrame*`, `InterfaceOptions_AddCategory`,
|
||||
`InterfaceOptionsFramePanelContainer`, `Settings.*`, `Enum.ClassMask`
|
||||
(only knows vanilla classes), retail `C_TooltipInfo`. Guard with
|
||||
`if X then … end` or fall back to a sensible default (`UIParent` for
|
||||
parent-frame fallbacks).
|
||||
|
||||
### FileDataIDs silently no-op
|
||||
`Set*Texture(<integer>)` does nothing on 3.3.5 — textures render as red
|
||||
placeholders. Use string paths. The comment next to an FDID call in
|
||||
upstream code usually already names the path.
|
||||
|
||||
### Hardcoded class lists miss CoA's 21 custom classes
|
||||
`SHAMAN/HERO` masks, `CLASS_SORT_ORDER` iteration, `RAID_CLASS_COLORS`
|
||||
direct keys, `CLASS_ICON_TCOORDS`. Witchdoctor / Templar / Sun Cleric /
|
||||
Primalist / Tinker / etc. won't appear. Extend via `GetNumClasses()`,
|
||||
`LOCALIZED_CLASS_NAMES_MALE` fallback, or a class-keyed `or { … }`
|
||||
guard.
|
||||
|
||||
### `C_ClassInfo.GetSpecInfo(class, spec)` arg mismatch
|
||||
`GetAllSpecs(class)` returns non-string items on this client. Always
|
||||
`pcall` the `GetSpecInfo` / `GetSpecInfoByID` call and skip iterations
|
||||
that fail.
|
||||
|
||||
### `StaticPopup_Show` during `PLAYER_LOGIN` silently fails
|
||||
Fires too early on this client. Defer with `C_Timer.After(0, …)`.
|
||||
Failure mode is silent — the popup never appears and any code that
|
||||
depends on user confirmation (e.g. WeakAuras' downgrade-repair flow)
|
||||
never runs.
|
||||
|
||||
### `.tga` textures don't load
|
||||
The engine only loads `.blp`. Ship BLP2 / DXT3 (`alphaEncoding = 1`) —
|
||||
DXT5 (`ae=7`) does NOT decode on 3.3.5. Conversion:
|
||||
|
||||
```sh
|
||||
blp-conv --blp-version blp2 --blp-format dxt3 --alpha-bits 8 in.png out.blp
|
||||
```
|
||||
|
||||
### `Minimap:SetMaskTexture("Interface\\BUTTONS\\WHITE8X8")` silently rounds
|
||||
The shared white mask used by retail SexyMap-style addons falls back to
|
||||
the round minimap on CoA. Bundle an opaque BLP and point the mask at it
|
||||
instead.
|
||||
|
||||
### `UnitClass("player")` at file-load time returns nil
|
||||
Resolve class inside `OnEnable` / event handler, not as a file-level
|
||||
`local`.
|
||||
|
||||
### CLEU argument positions changed
|
||||
Verify against the 3.3.5 signature:
|
||||
|
||||
```
|
||||
(event, timestamp, subevent, hideCaster,
|
||||
srcGUID, srcName, srcFlags, srcRaidFlags,
|
||||
destGUID, destName, destFlags, destRaidFlags,
|
||||
spellId, spellName, spellSchool, …)
|
||||
```
|
||||
|
||||
`destFlags` is arg 11, not arg 9. Many retail-era addons get this
|
||||
wrong.
|
||||
|
||||
## Ace3 specifics
|
||||
|
||||
If the addon embeds Ace3 libs (`Libs/AceXxx-3.0/`), use the canonical
|
||||
`Exiles/coa-ace3` bundle to overwrite them. The sweep script in that
|
||||
repo handles every fork in one pass — see its README. Don't ship a
|
||||
bespoke Ace3 vendor; mismatched MINOR versions across loaded addons
|
||||
cause silent breakage at LibStub resolution time.
|
||||
|
||||
`coa-elvui` is the one exception — ElvUI ships its own customized
|
||||
Ace3 stack and is excluded from the sweep.
|
||||
|
||||
## Standard layout
|
||||
|
||||
The Exiles fork-layout convention is `<repo>/<AddonFolder>/<AddonFolder>.toc`
|
||||
at depth-1, with dev tooling (`tools/`, `.gitea/`, `README.md`, `LICENSE`,
|
||||
`PORTING.md`) at the repo root. Multi-addon repos place each addon in its
|
||||
own sibling folder.
|
||||
|
||||
`tools/build_zip.sh` discovers these `<Folder>/<Folder>.toc` pairs
|
||||
automatically.
|
||||
|
||||
## Tagging convention
|
||||
|
||||
`<upstream>-coa.N` per repo. Examples:
|
||||
|
||||
| Repo | Tag |
|
||||
|---|---|
|
||||
| `coa-decursive` | `Asc-1.1.6-coa.1` |
|
||||
| `coa-leatrix-plus` | `3.3.5-coa.1` |
|
||||
| `coa-ace3` | `52e5f2c-coa.1` (upstream commit pin) |
|
||||
| `coa-dbm` | `2026.05.25-coa.1` (no `## Version:` line; date-based) |
|
||||
|
||||
The trailing `-coa.N` counter bumps for each CoA-fork iteration. Pushing
|
||||
the tag fires the release workflow and publishes the per-addon zips to
|
||||
`https://git.sub-net.at/Exiles/<repo>/releases/tag/<tag>`.
|
||||
|
||||
See [coa.exil.es/coa/dev/releases](https://coa.exil.es/coa/dev/releases)
|
||||
for the full release pipeline doc.
|
||||
Reference in New Issue
Block a user