mirror of
https://github.com/DramaticShape/DramaticShapeVoxelMod.git
synced 2026-08-12 16:21:05 +02:00
201 lines
7.0 KiB
YAML
201 lines
7.0 KiB
YAML
name: Release
|
|
|
|
# Packs the mod into an installable .zip and publishes it as a GitHub Release,
|
|
# once per push to main.
|
|
#
|
|
# Archive layout: every mod file at the archive root, manifest.json included.
|
|
# That is one of the two shapes the game accepts on MODS > Import mod .zip
|
|
# (src/mods/LauncherMods.lua locateRoot: manifest at the root, or inside a
|
|
# single top-level folder). Nothing else is added, so the archive stays
|
|
# installable by hand too.
|
|
#
|
|
# Versioning, first rule that applies wins:
|
|
# 1. the "version" input of a manual run,
|
|
# 2. "[release X.Y.Z]" anywhere in the commit message,
|
|
# 3. manifest.json's own version, when it is ahead of every existing tag,
|
|
# so bumping the manifest is the normal way to cut a release,
|
|
# 4. otherwise the newest vX.Y.Z tag with its patch incremented
|
|
# (0.2.99 rolls over to 0.3.0).
|
|
# Whichever wins is written into the manifest.json inside the archive, so a
|
|
# shipped mod never reports a different version than the release it came from.
|
|
#
|
|
# Generated by: python3 tools/modkit.py add-release-workflow <mod-id>
|
|
# MOD_ID below is stamped to this mod's id when the file is copied.
|
|
|
|
on:
|
|
push:
|
|
branches: [master]
|
|
paths-ignore:
|
|
- '.github/**'
|
|
- '**.md'
|
|
workflow_dispatch:
|
|
inputs:
|
|
version:
|
|
description: "Exact version to release (e.g. 0.3.0). Leave blank to auto-resolve."
|
|
required: false
|
|
default: ""
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
concurrency:
|
|
group: release
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Determine version
|
|
id: ver
|
|
env:
|
|
DISPATCH_VERSION: ${{ github.event.inputs.version }}
|
|
run: |
|
|
set -euo pipefail
|
|
python3 - <<'PY' >> "$GITHUB_OUTPUT"
|
|
import json, os, re, subprocess, sys
|
|
|
|
SEMVER = re.compile(r"^(\d+)\.(\d+)\.(\d+)$")
|
|
|
|
def sh(*args):
|
|
return subprocess.run(args, capture_output=True, text=True).stdout.strip()
|
|
|
|
def parse(text):
|
|
m = SEMVER.match(text)
|
|
return tuple(int(p) for p in m.groups()) if m else None
|
|
|
|
def die(msg):
|
|
print(f"::error::{msg}", file=sys.stderr)
|
|
raise SystemExit(1)
|
|
|
|
with open("manifest.json", encoding="utf-8") as fh:
|
|
manifest_version = str(json.load(fh).get("version", ""))
|
|
|
|
released = sorted(
|
|
v for v in (parse(tag[1:]) for tag in sh("git", "tag", "-l", "v*").splitlines()) if v
|
|
)
|
|
latest = released[-1] if released else None
|
|
|
|
override = os.environ.get("DISPATCH_VERSION", "").strip()
|
|
if not override:
|
|
found = re.search(r"\[release\s+(\d+\.\d+\.\d+)\]", sh("git", "log", "-1", "--pretty=%B"))
|
|
override = found.group(1) if found else ""
|
|
|
|
manifest_ver = parse(manifest_version)
|
|
if override:
|
|
version = parse(override) or die(f"invalid version override {override!r} (expected X.Y.Z)")
|
|
source = "the override"
|
|
elif manifest_ver and (latest is None or manifest_ver > latest):
|
|
version = manifest_ver
|
|
source = "manifest.json"
|
|
elif latest:
|
|
major, minor, patch = latest
|
|
patch += 1
|
|
if patch > 99:
|
|
minor, patch = minor + 1, 0
|
|
version = (major, minor, patch)
|
|
source = "a patch bump on v%d.%d.%d" % latest
|
|
else:
|
|
die(f"manifest.json version {manifest_version!r} is not X.Y.Z "
|
|
"and there is no vX.Y.Z tag to count from")
|
|
|
|
text = "%d.%d.%d" % version
|
|
print(f"Releasing {text}, from {source}.", file=sys.stderr)
|
|
print(f"version={text}")
|
|
print(f"tag=v{text}")
|
|
PY
|
|
|
|
- name: Refuse to clobber an existing release
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
TAG: ${{ steps.ver.outputs.tag }}
|
|
run: |
|
|
set -euo pipefail
|
|
if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
|
|
echo "::error::Tag $TAG already exists. Pick a different version."
|
|
exit 1
|
|
fi
|
|
if gh release view "$TAG" >/dev/null 2>&1; then
|
|
echo "::error::Release $TAG already exists. Pick a different version."
|
|
exit 1
|
|
fi
|
|
|
|
- name: Build the mod .zip
|
|
env:
|
|
VERSION: ${{ steps.ver.outputs.version }}
|
|
MOD_ID: "DRAMATIC_SHAPE"
|
|
run: |
|
|
set -euo pipefail
|
|
staging="$RUNNER_TEMP/pkg"
|
|
out="$GITHUB_WORKSPACE/dist"
|
|
rm -rf "$staging" "$out"
|
|
mkdir -p "$staging" "$out"
|
|
|
|
git archive HEAD | tar -x -C "$staging"
|
|
|
|
rm -rf "$staging/.github" "$staging/.gitattributes" \
|
|
"$staging/.gitignore" "$staging/.luarc.json"
|
|
|
|
python3 - "$staging/manifest.json" "$VERSION" <<'PY'
|
|
import json, sys
|
|
path, version = sys.argv[1], sys.argv[2]
|
|
with open(path, encoding="utf-8") as fh:
|
|
manifest = json.load(fh)
|
|
manifest["version"] = version
|
|
with open(path, "w", encoding="utf-8") as fh:
|
|
json.dump(manifest, fh, indent=2, ensure_ascii=False)
|
|
fh.write("\n")
|
|
PY
|
|
|
|
zip_path="$out/${MOD_ID}-${VERSION}.zip"
|
|
(cd "$staging" && zip -qr "$zip_path" .)
|
|
unzip -l "$zip_path"
|
|
|
|
unzip -p "$zip_path" manifest.json > "$RUNNER_TEMP/packed-manifest.json"
|
|
python3 - "$RUNNER_TEMP/packed-manifest.json" "$VERSION" <<'PY'
|
|
import json, sys
|
|
path, expected = sys.argv[1], sys.argv[2]
|
|
with open(path, encoding="utf-8") as fh:
|
|
version = json.load(fh)["version"]
|
|
if version != expected:
|
|
raise SystemExit(f"::error::packed manifest says {version}, expected {expected}")
|
|
print(f"manifest.json is at the archive root and reports {version}")
|
|
PY
|
|
|
|
(cd "$out" && sha256sum "${MOD_ID}"-*.zip > sha256sums.txt)
|
|
cat "$out/sha256sums.txt"
|
|
|
|
- name: Publish GitHub Release
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
VERSION: ${{ steps.ver.outputs.version }}
|
|
TAG: ${{ steps.ver.outputs.tag }}
|
|
MOD_ID: "DRAMATIC_SHAPE"
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
prev="$(git tag -l 'v*' --sort=-v:refname | grep -v "^${TAG}$" | head -1 || true)"
|
|
range="${prev:+${prev}..}$GITHUB_SHA"
|
|
changes="$(git log --no-merges --pretty='- %s' "$range" | head -50 || true)"
|
|
|
|
notes=$'Download the .zip and install it from the game: MODS > Import mod .zip.'
|
|
if [ -n "$changes" ]; then
|
|
notes+=$'\n\n## Changes\n\n'"$changes"
|
|
fi
|
|
printf 'Release notes:\n%s\n' "$notes"
|
|
|
|
gh release create "$TAG" \
|
|
--target "$GITHUB_SHA" \
|
|
--title "$VERSION" \
|
|
--notes "$notes" \
|
|
"dist/${MOD_ID}-${VERSION}.zip" \
|
|
"dist/sha256sums.txt"
|
|
|
|
echo "Published release $TAG"
|