paste 4293e90a97 Initial: MPQ patch packager (Gitea Action, StormLib-based)
A BigWigs-style CI packager for WoW MPQ patch archives. Reads an mpq.yaml
manifest, stages files, builds a vanilla-1.12-compatible patch-X.mpq via
StormLib, and (in the example workflow) attaches it to a Gitea release on tag.
2026-06-25 21:36:50 -05:00
2026-06-26 02:27:18 +00:00

mpq-packager

A CI packager for World of Warcraft MPQ patch archives — the MPQ equivalent of BigWigsMods/packager. Point it at a WoW interface repo and it produces a vanilla-1.12-compatible patch-X.mpq, ready to attach to a Gitea release.

It runs as a Gitea Action on a Linux runner. MPQs are built with StormLib (the MoPaQ library Ladik's MPQ Editor is itself built on) so no Windows host or Wine is needed.

What it does

  1. Reads a manifest (mpq.yaml) describing what to pack and where it lands inside the archive.
  2. Stages the selected files, honouring ignore globs.
  3. Optionally substitutes @project-version@ / @project-revision@ / @project-date-iso@ tokens in text files.
  4. Names the output patch-<letter>.mpq — vanilla 1.12's loader only accepts a single-character suffix (patch-Z.mpq , patch-myproject.mpq ).
  5. Builds the archive as MPQ format v1 with zlib-compressed sectors and a (listfile).

Usage in a consuming repo

Add a manifest at the repo root (mpq.yaml):

name: GlueXML
patch-letter: Z          # high letters sort last → win on conflict
substitute:
  enabled: true
  extensions: [".lua", ".xml", ".toc"]
contents:
  - src: .                # repo root
    dest: Interface/GlueXML   # in-MPQ path (slashes become backslashes)
    ignore:
      - ".git/**"
      - ".gitea/**"
      - "mpq.yaml"
      - "*.md"

Add a release workflow at .gitea/workflows/release.yml (see examples/release.yml). Pushing a tag like v1.0.0 builds the MPQ and attaches it to a matching Gitea release:

- uses: paste/mpq-packager@v1
  id: pack
  with:
    manifest: mpq.yaml
    version: ${{ github.ref_name }}
# steps.pack.outputs.mpq-path / mpq-name point at the built archive

Working examples for the GlueXML repo live in examples/.

Manifest reference

Key Default Meaning
name Cosmetic, used in logs.
patch-letter Z Single char; becomes patch-<letter>.mpq.
max-files file count + 16 Hash-table sizing hint (StormLib rounds up to a power of two).
substitute disabled enabled + extensions list for @token@ replacement.
contents[].src . Repo-relative file or directory to pack.
contents[].dest In-MPQ destination path (forward slashes; converted to \).
contents[].ignore [] Glob patterns matched against repo-relative paths.

Action inputs / outputs

Input Default Description
manifest mpq.yaml Manifest path, relative to repo root.
version ref name Stamped into @project-version@.
out-dir dist Where the .mpq is written.
Output Description
mpq-path Filesystem path of the built .mpq.
mpq-name Filename, e.g. patch-Z.mpq.

Prerequisites

  • Actions enabled on the consuming repo (repo Settings → Actions).
  • An act_runner registered to your Gitea instance advertising a label your workflow's runs-on uses (e.g. ubuntu-latest), with Docker available.

Local build & test

docker build -t mpq-packager .
docker run --rm \
  -e INPUT_MANIFEST=mpq.yaml -e INPUT_VERSION=v0.0.0 \
  -e INPUT_OUT_DIR=/work/dist -e GITHUB_WORKSPACE=/work \
  -v "$PWD/test:/work" mpq-packager
# -> test/dist/patch-Z.mpq

Layout

Path Role
src/mpqpack.c StormLib-based packer: staging dir → MPQ v1.
package.py Orchestration: manifest, staging, ignores, substitution.
entrypoint.sh Action entrypoint wiring INPUT_* env to package.py.
Dockerfile Builds StormLib + mpqpack; ships the runtime image.
action.yml Gitea/GitHub Docker action definition.
examples/ Manifest + release workflow for a consuming repo.
test/ Fixture + manifest exercised by CI.

Notes & caveats

  • Blizzard_* addons still go through the engine's .toc.sig check regardless of MPQ residency — packaging them here does not bypass it.
  • Compression is zlib, which vanilla 1.12.1 decompresses. The output is MPQ v1 specifically; v2+ headers are not read by the 1.12 loader.
  • See ClassicAPI docs/MPQBuilding.md for the empirical background on the naming constraint and load-order behaviour.
S
Description
No description provided
Readme MIT 61 KiB
Languages
Python 44.4%
C 34.4%
Dockerfile 13.2%
Shell 6.5%
Lua 1.5%