Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .github/release/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

LINES = ("1.21.1", "1.21.4", "1.21.8", "1.21.11", "26.1", "26.2", "26.3")
ANCHOR = "26.1"
VERSION = r"(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)"
VERSION_CORE = r"(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)"
VERSION = rf"{VERSION_CORE}(?:\+(?:alpha|beta|pre-release|rc|build|hotfix)\.(?:0|[1-9][0-9]*))?"
VERSION_LINE = re.compile(rb"(?m)^(mod_version[ \t]*=[ \t]*)([^\s#]+)([ \t]*)(?=\r?$)")


Expand Down Expand Up @@ -52,11 +53,19 @@ def contents(path, ref):
return base64.b64decode(data["content"])


def release_type(version):
require(re.fullmatch(VERSION, version), f"Invalid release version: {version}")
qualifier = version.partition("+")[2].partition(".")[0]
if qualifier == "alpha":
return "alpha"
return "beta" if qualifier in {"beta", "pre-release", "rc"} else "release"


def mod_version(properties):
matches = VERSION_LINE.findall(properties)
require(len(matches) == 1, "Expected one mod_version property")
version = matches[0][1].decode()
require(re.fullmatch(VERSION, version), f"Invalid release version: {version}")
release_type(version)
return version


Expand Down
9 changes: 5 additions & 4 deletions .github/release/mod_sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from urllib.error import HTTPError
from urllib.request import Request, urlopen

from common import (commit_status, digest, gh, github, record, repo, require, summary,
from common import (commit_status, digest, gh, github, record, release_type, repo, require, summary,
tag_manifest)

MODRINTH = "https://api.modrinth.com/v2"
Expand Down Expand Up @@ -81,6 +81,7 @@ def send(sha, context, upload, reconcile=None):

def publish_modrinth(plan, line, folder, context):
t = plan["targets"][line]
kind = release_type(plan["version"])
token = os.environ["MODRINTH_TOKEN"]
require(token, "Missing MODRINTH_TOKEN")
files = {name: folder / name for name in t["files"]}
Expand All @@ -97,14 +98,14 @@ def reconcile():
return None
raise
require(remote["project_id"] == t["modrinth"] and remote["version_number"] == plan["version"]
and remote["version_type"] == "release" and t["game"] in remote["game_versions"]
and remote["version_type"] == kind and t["game"] in remote["game_versions"]
and "neoforge" in remote["loaders"]
and {f["filename"]: f["hashes"]["sha512"] for f in remote["files"]} == hashes,
"Modrinth has the JAR with different release metadata")
return remote["id"]

metadata = {"project_id": t["modrinth"], "version_number": plan["version"],
"name": f"AnvilLib {plan['version']} · NeoForge {t['game']}", "version_type": "release",
"name": f"AnvilLib {plan['version']} · NeoForge {t['game']}", "version_type": kind,
"changelog": release_url(plan), "dependencies": [], "game_versions": [t["game"]],
"loaders": ["neoforge"], "featured": False, "primary_file": t["jar"], "file_parts": list(files),
"file_types": {n: "sources-jar" if n.endswith("-sources.jar") else "javadoc-jar"
Expand All @@ -122,7 +123,7 @@ def publish_curseforge(plan, line, folder, context):
token = os.environ["CURSEFORGE_TOKEN"]
require(token, "Missing CURSEFORGE_TOKEN")
url = f"{CURSEFORGE}/projects/{t['curseforge']}/upload-file"
base = {"changelog": release_url(plan), "changelogType": "markdown", "releaseType": "release"}
base = {"changelog": release_url(plan), "changelogType": "markdown", "releaseType": release_type(plan["version"])}
primary = dict(base, displayName=f"AnvilLib {plan['version']} · NeoForge {t['game']}",
gameVersionNames=[t["game"], "NeoForge", "Client", "Server"])

Expand Down
27 changes: 22 additions & 5 deletions .github/release/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from urllib.parse import quote

from common import (ANCHOR, LINES, VERSION_LINE, artifact, commit_status, contents, digest, gh, github,
mod_version, output, repo, require, summary, tag_manifest)
mod_version, output, release_type, repo, require, summary, tag_manifest)


def prepare():
Expand Down Expand Up @@ -37,6 +37,10 @@ def prepare():
version = versions[ANCHOR]
plan = {"repo": repo(), "tag": "v" + version, "version": version,
"run": os.environ["GITHUB_RUN_ID"], "targets": targets}
if os.environ.get("GENERATE_RELEASE_NOTES") == "true":
plan["release_notes"] = github("releases/generate-notes", {
"tag_name": plan["tag"], "target_commitish": targets[ANCHOR]["sha"],
})["body"]
plan_file.write_text(json.dumps(plan, indent=2) + "\n")
if os.environ.get("DRY_RUN") != "true":
existing = tag_manifest(plan["tag"])
Expand All @@ -47,6 +51,7 @@ def prepare():
output("matrix", json.dumps(rows))
output("version", plan["version"])
output("tag", plan["tag"])
output("bump_patch", str("+" not in plan["version"]).lower())
output("new", str(not saved).lower())
summary(f"**{plan['tag']}**\n\n" + "\n".join(f"- dev/{r['line']} @ {r['sha']}" for r in rows))

Expand Down Expand Up @@ -77,8 +82,11 @@ def verify_assets(release, targets):
def seal():
plan = json.loads(Path("release-plan.json").read_text())
tag = plan["tag"]
notes = [f"AnvilLib {plan['version']} · NeoForge", "",
"| Minecraft | Source | JAR | SHA-256 |", "|---|---|---|---|"]
prerelease = release_type(plan["version"]) != "release"
notes = [f"AnvilLib {plan['version']} · NeoForge", ""]
if plan.get("release_notes"):
notes.extend([plan["release_notes"], ""])
notes.extend(["| Minecraft | Source | JAR | SHA-256 |", "|---|---|---|---|"])
paths = {}
for line, target in plan["targets"].items():
folder = Path("bundles") / f"build-{line}" / "dist"
Expand Down Expand Up @@ -106,7 +114,9 @@ def seal():
release = release_by_tag(tag)
if not release:
release = github("releases", {"tag_name": tag, "name": f"AnvilLib {plan['version']}",
"body": "\n".join(notes), "draft": True})
"target_commitish": plan["targets"][ANCHOR]["sha"],
"body": "\n".join(notes), "draft": True, "prerelease": prerelease})
require(release.get("prerelease", False) == prerelease, f"Conflicting release type for {tag}")
assets = {a["name"]: a for a in release["assets"]}
for name, path in paths.items():
old = assets.get(name)
Expand All @@ -124,19 +134,26 @@ def seal():
def publish(tag):
plan = tag_manifest(tag)
release = release_by_tag(tag)
prerelease = release_type(plan["version"]) != "release"
require(release.get("prerelease", False) == prerelease, f"Conflicting release type for {tag}")
verify_assets(release, plan["targets"])
for line, target in plan["targets"].items():
status = commit_status(target["sha"], f"release/{tag}/{line}/central")
require(status and status["state"] == "success", f"Central has not published {line}")
if release["draft"]:
release = github(f"releases/{release['id']}", {"draft": False}, method="PATCH")
release = github(f"releases/{release['id']}", {
"draft": False, "prerelease": prerelease, "make_latest": "false" if prerelease else "true",
}, method="PATCH")
summary(f"Published [{tag}]({release['html_url']}).")


def bump(tag, line):
plan = tag_manifest(tag)
require(line in LINES and not release_by_tag(tag)["draft"], "Bump requires a public release")
version = plan["version"]
if "+" in version:
summary(f"{tag} has a version qualifier; skipping the patch bump for dev/{line}.")
return
major, minor, patch = version.split(".")
next_version = f"{major}.{minor}.{int(patch) + 1}"
base = "dev/" + line
Expand Down
4 changes: 3 additions & 1 deletion .github/release/test_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ def status(sha, context):
github.assert_not_called()
else:
release.publish(TAG)
github.assert_called_once_with("releases/42", {"draft": False}, method="PATCH")
github.assert_called_once_with("releases/42", {
"draft": False, "prerelease": False, "make_latest": "true",
}, method="PATCH")

def test_missing_or_changed_asset_blocks_publication(self):
for assets in [DRAFT["assets"][:-1], [dict(DRAFT["assets"][0], digest="changed"), *DRAFT["assets"][1:]]]:
Expand Down
Loading
Loading