Skip to content

Commit 62136dd

Browse files
authored
chore: standardize repository for TFMC (#1)
* chore: standardize repository for TFMC * docs: align README with project convention * build: pin released SimpleFactions API
1 parent 78424ed commit 62136dd

41 files changed

Lines changed: 845 additions & 228 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/dependencies.sha256‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439 libs/json-simple-1.1.jar
2+
0116d714822b6f0cfebfe833a5df2e4754797b637d0fe709afb762c56da463a3 libs/ItemsAdder_3.5.0-r2.jar
3+
c84700df5942fd969d3e8c2f1ad2c3ebeb17987ef88b426408d1306e49c4aada libs/MMOItems-6.10.jar
4+
660ff2a6ec86bc8d7779948cf65c1637e271a16e1ef812d6a273f4a5c5eec73c libs/MythicLib-1.7.jar
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
# Run from the repository root after downloading the pinned JARs.
4+
# Hash-qualified versions prevent different private JARs sharing a Maven cache key.
5+
sha256sum --check .github/dependencies.sha256
6+
7+
mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \
8+
-Dfile="libs/json-simple-1.1.jar" -DgroupId="local" -DartifactId="json-simple" \
9+
-Dversion="1.1-tfmc-2d9484f4c649" -Dpackaging=jar -DgeneratePom=true "$@"
10+
mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \
11+
-Dfile="libs/ItemsAdder_3.5.0-r2.jar" -DgroupId="local" -DartifactId="ItemsAdder" \
12+
-Dversion="3.5.0-tfmc-0116d714822b" -Dpackaging=jar -DgeneratePom=true "$@"
13+
mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \
14+
-Dfile="libs/MMOItems-6.10.jar" -DgroupId="local" -DartifactId="MMOItems" \
15+
-Dversion="6.10-tfmc-c84700df5942" -Dpackaging=jar -DgeneratePom=true "$@"
16+
mvn -B --no-transfer-progress org.apache.maven.plugins:maven-install-plugin:3.1.4:install-file \
17+
-Dfile="libs/MythicLib-1.7.jar" -DgroupId="local" -DartifactId="MythicLib" \
18+
-Dversion="1.7-tfmc-660ff2a6ec86" -Dpackaging=jar -DgeneratePom=true "$@"

‎.github/scripts/plugin-artifact.py‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python3
2+
"""Validate the Maven runtime JAR and optionally stage a release bundle."""
3+
import argparse
4+
import hashlib
5+
import json
6+
import os
7+
from pathlib import Path
8+
import re
9+
import shutil
10+
import zipfile
11+
12+
13+
def validate(source, version):
14+
source = Path(source).resolve()
15+
target = Path.cwd().resolve() / "target"
16+
if not source.is_relative_to(target) or not source.is_file():
17+
raise ValueError("Expected the Maven runtime JAR inside target/")
18+
if not re.fullmatch(r"[a-z][a-z0-9]*-" + re.escape(version) + r"\.jar", source.name):
19+
raise ValueError("Runtime JAR filename must use a lowercase alphanumeric name followed by the Maven version")
20+
with zipfile.ZipFile(source) as jar:
21+
descriptors = {"plugin.yml", "paper-plugin.yml"}.intersection(jar.namelist())
22+
if not descriptors:
23+
raise ValueError("Runtime JAR has no plugin descriptor")
24+
if jar.testzip() is not None:
25+
raise ValueError("Runtime JAR is corrupt")
26+
for name in descriptors:
27+
text = jar.read(name).decode("utf-8-sig")
28+
versions = re.findall(
29+
r'''^version:[ \t]*(?:"([^"\r\n]*)"|'([^'\r\n]*)'|([^\s#]+))(?:(?:[ \t]+\#[^\r\n]*)|[ \t]*)\r?$''',
30+
text, re.MULTILINE,
31+
)
32+
if len(versions) != 1 or next((v for v in versions[0] if v), "") != version:
33+
raise ValueError(f"{name} version must match Maven version {version}")
34+
return source
35+
36+
37+
def main():
38+
parser = argparse.ArgumentParser(description=__doc__)
39+
parser.add_argument("--jar", required=True, type=Path)
40+
parser.add_argument("--version", required=True)
41+
parser.add_argument("--stage", type=Path)
42+
parser.add_argument("--dependencies", type=Path)
43+
args = parser.parse_args()
44+
try:
45+
source = validate(args.jar, args.version)
46+
if args.stage:
47+
if os.environ["TAG"] != f"v{args.version}":
48+
raise ValueError("Release tag must match the Maven version")
49+
dependencies = json.loads(args.dependencies.read_text()) if args.dependencies else []
50+
digest = hashlib.sha256(source.read_bytes()).hexdigest()
51+
metadata = {
52+
"repository": os.environ["GITHUB_REPOSITORY"],
53+
"commit": os.environ["GITHUB_SHA"],
54+
"tag": os.environ["TAG"],
55+
"run": f"{os.environ['GITHUB_SERVER_URL']}/{os.environ['GITHUB_REPOSITORY']}/actions/runs/{os.environ['GITHUB_RUN_ID']}",
56+
"plugin_dependencies": dependencies,
57+
"artifact": source.name,
58+
"sha256": digest,
59+
}
60+
args.stage.mkdir()
61+
shutil.copyfile(source, args.stage / source.name)
62+
(args.stage / "SHA256SUMS").write_text(f"{digest} {source.name}\n")
63+
(args.stage / "build.json").write_text(json.dumps(metadata, indent=2) + "\n")
64+
print(f"Verified {source.name}: filename and embedded version match {args.version}")
65+
except (ValueError, OSError, KeyError, zipfile.BadZipFile) as error:
66+
parser.exit(1, f"Plugin artifact validation failed: {error}\n")
67+
68+
69+
if __name__ == "__main__":
70+
main()

‎.github/scripts/prepare-release.sh‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
: "${GH_TOKEN:?Set DEPS_TOKEN with Contents read access to TF-Minecraft/ServerAssets}"
4+
ref=883970ddc256f0e4c3bcaee87e6cf33171b9d4a4
5+
mkdir -p libs
6+
curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/2d9484f4c649/json-simple-1.1.jar?ref=$ref" > "libs/json-simple-1.1.jar"
7+
curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/0116d714822b/ItemsAdder_3.5.0-r2.jar?ref=$ref" > "libs/ItemsAdder_3.5.0-r2.jar"
8+
curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/c84700df5942/MMOItems-6.10.jar?ref=$ref" > "libs/MMOItems-6.10.jar"
9+
curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/660ff2a6ec86/MythicLib-1.7.jar?ref=$ref" > "libs/MythicLib-1.7.jar"
10+
bash .github/scripts/install-local-dependencies.sh "$@"

‎.github/workflows/build.yml‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-24.04
15+
timeout-minutes: 20
16+
steps:
17+
- uses: actions/checkout@v7
18+
with:
19+
persist-credentials: false
20+
- uses: actions/setup-java@v6
21+
with:
22+
distribution: temurin
23+
java-version: '21'
24+
- name: Install shared plugin dependencies
25+
uses: TF-Minecraft/TLibs/.github/actions/setup-plugins@4f7a3545063cb2e8d06a034687c817ab863f0835
26+
with:
27+
mode: pinned
28+
private-token: ${{ secrets.DEPS_TOKEN }}
29+
30+
- name: Prepare pinned dependencies
31+
env:
32+
GH_TOKEN: ${{ secrets.DEPS_TOKEN }}
33+
run: bash .github/scripts/prepare-release.sh
34+
- name: Set build version
35+
id: dev
36+
shell: bash
37+
run: |
38+
dev_version="main-SNAPSHOT"
39+
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
40+
dev_version="DEV-$(date -u +%Y%m%d-%H%M)"
41+
fi
42+
mvn -B --no-transfer-progress -P'!deploy-live' org.codehaus.mojo:versions-maven-plugin:2.22.0:set \
43+
-DnewVersion="$dev_version" -DgenerateBackupPoms=false
44+
mvn -B --no-transfer-progress -P'!deploy-live' help:evaluate \
45+
-Dexpression=project.build.finalName -Doutput="$RUNNER_TEMP/final-name"
46+
final_name=$(cat "$RUNNER_TEMP/final-name")
47+
[[ "$final_name" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] || exit 1
48+
echo "version=$dev_version" >> "$GITHUB_OUTPUT"
49+
echo "name=$final_name" >> "$GITHUB_OUTPUT"
50+
echo "jar=target/$final_name.jar" >> "$GITHUB_OUTPUT"
51+
52+
- name: Run unit tests and build
53+
run: mvn -B --no-transfer-progress -P'!deploy-live' clean verify -DskipTests=false -Dmaven.test.skip=false
54+
55+
- name: Verify runtime JAR
56+
env:
57+
ARTIFACT_PATH: ${{ steps.dev.outputs.jar }}
58+
BUILD_VERSION: ${{ steps.dev.outputs.version }}
59+
run: python3 .github/scripts/plugin-artifact.py --jar "$ARTIFACT_PATH" --version "$BUILD_VERSION"
60+
61+
- if: github.event_name == 'pull_request'
62+
uses: actions/upload-artifact@v7
63+
with:
64+
name: ${{ steps.dev.outputs.name }}-${{ github.run_id }}-${{ github.run_attempt }}
65+
path: |
66+
${{ steps.dev.outputs.jar }}
67+
.build/plugin-dependencies.json
68+
include-hidden-files: true
69+
if-no-files-found: error
70+
71+
- name: Upload unit test reports
72+
if: ${{ !cancelled() && hashFiles('target/surefire-reports/*.xml') != '' }}
73+
uses: actions/upload-artifact@v7
74+
with:
75+
name: unit-test-reports-${{ github.run_id }}-${{ github.run_attempt }}
76+
path: target/surefire-reports/
77+
if-no-files-found: error
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
name: Maven plugin release
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
java-version:
7+
required: true
8+
type: string
9+
secrets:
10+
DEPS_TOKEN:
11+
required: false
12+
13+
permissions:
14+
contents: read
15+
16+
concurrency:
17+
group: plugin-release-${{ github.repository }}-${{ github.ref }}
18+
cancel-in-progress: false
19+
20+
defaults:
21+
run:
22+
shell: bash
23+
24+
jobs:
25+
build:
26+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
27+
runs-on: ubuntu-24.04
28+
timeout-minutes: 20
29+
steps:
30+
- uses: actions/checkout@v7
31+
with:
32+
persist-credentials: false
33+
34+
- uses: actions/setup-java@v6
35+
with:
36+
distribution: temurin
37+
java-version: ${{ inputs.java-version }}
38+
39+
- name: Validate release version
40+
env:
41+
TAG: ${{ github.ref_name }}
42+
run: |
43+
[[ "$TAG" =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$ ]] || {
44+
echo '::error::Expected vMAJOR.MINOR or vMAJOR.MINOR.PATCH, with an optional prerelease suffix.'
45+
exit 1
46+
}
47+
[[ "${TAG^^}" != *SNAPSHOT* ]] || exit 1
48+
49+
- name: Install shared plugin dependencies
50+
uses: TF-Minecraft/TLibs/.github/actions/setup-plugins@4f7a3545063cb2e8d06a034687c817ab863f0835
51+
with:
52+
mode: pinned
53+
private-token: ${{ secrets.DEPS_TOKEN }}
54+
55+
- name: Prepare pinned dependencies
56+
env:
57+
GH_TOKEN: ${{ secrets.DEPS_TOKEN }}
58+
run: |
59+
if [[ -f .github/scripts/prepare-release.sh ]]; then
60+
bash .github/scripts/prepare-release.sh
61+
fi
62+
63+
- name: Set version from tag and build
64+
id: maven
65+
env:
66+
TAG: ${{ github.ref_name }}
67+
run: |
68+
mvn -B --no-transfer-progress -P'!deploy-live' org.codehaus.mojo:versions-maven-plugin:2.22.0:set \
69+
-DnewVersion="${TAG#v}" -DgenerateBackupPoms=false
70+
mvn -B --no-transfer-progress -P'!deploy-live' help:evaluate \
71+
-Dexpression=project.build.finalName -Doutput="$RUNNER_TEMP/final-name"
72+
final_name=$(cat "$RUNNER_TEMP/final-name")
73+
[[ "$final_name" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]] || exit 1
74+
echo "jar=target/$final_name.jar" >> "$GITHUB_OUTPUT"
75+
mvn -B --no-transfer-progress -P'!deploy-live' clean verify -DskipTests=false -Dmaven.test.skip=false
76+
77+
- name: Stage only the release JAR
78+
env:
79+
ARTIFACT_PATH: ${{ steps.maven.outputs.jar }}
80+
TAG: ${{ github.ref_name }}
81+
run: |
82+
python3 .github/scripts/plugin-artifact.py \
83+
--jar "$ARTIFACT_PATH" --version "${TAG#v}" \
84+
--stage "$RUNNER_TEMP/plugin-release" \
85+
--dependencies .build/plugin-dependencies.json
86+
87+
- uses: actions/upload-artifact@v7
88+
with:
89+
name: plugin-release-${{ github.sha }}
90+
path: ${{ runner.temp }}/plugin-release/
91+
if-no-files-found: error
92+
retention-days: 30
93+
94+
publish:
95+
needs: build
96+
runs-on: ubuntu-24.04
97+
timeout-minutes: 5
98+
permissions:
99+
contents: write
100+
steps:
101+
- uses: actions/download-artifact@v8
102+
with:
103+
name: plugin-release-${{ github.sha }}
104+
path: release
105+
106+
- name: Create draft release
107+
working-directory: release
108+
env:
109+
GH_TOKEN: ${{ github.token }}
110+
GH_REPO: ${{ github.repository }}
111+
TAG: ${{ github.ref_name }}
112+
run: |
113+
sha256sum --check SHA256SUMS
114+
flags=()
115+
if [[ "$TAG" == *-* ]]; then flags+=(--prerelease); fi
116+
gh api --method POST "repos/$GH_REPO/releases/generate-notes" \
117+
-f tag_name="$TAG" --jq .body > "$RUNNER_TEMP/release-changes.md"
118+
python3 - <<'PY'
119+
import os, re
120+
from pathlib import Path
121+
from urllib.parse import quote
122+
temp = Path(os.environ['RUNNER_TEMP'])
123+
changes = (temp / 'release-changes.md').read_text().strip()
124+
changes = re.sub(r"^## What's Changed\s*", '', changes)
125+
changes = re.sub(r'^(#{1,5}) ', r'\1# ', changes, flags=re.MULTILINE)
126+
lines = ['## Changes', '', changes or 'Initial release.', '', '## Downloads', '']
127+
assets = sorted([*Path('.').glob('*.jar'), *Path('.').glob('*.tar.gz')])
128+
assets += [Path('SHA256SUMS'), Path('build.json')]
129+
base = f"https://github.com/{os.environ['GH_REPO']}/releases/download/{quote(os.environ['TAG'], safe='')}/"
130+
for asset in assets:
131+
if not asset.is_file():
132+
raise SystemExit(f'Missing release asset: {asset}')
133+
description = {'SHA256SUMS': ' — SHA-256 checksums.', 'build.json': ' — Build metadata.'}.get(asset.name, '')
134+
lines.append(f'- [`{asset.name}`]({base}{quote(asset.name)}){description}')
135+
(temp / 'release-notes.md').write_text('\n'.join(lines) + '\n')
136+
PY
137+
gh release create "$TAG" ./*.jar SHA256SUMS build.json \
138+
--verify-tag --draft --title "$TAG" --notes-file "$RUNNER_TEMP/release-notes.md" "${flags[@]}"

‎.github/workflows/release.yml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags: ['v*']
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
release:
12+
permissions:
13+
contents: write
14+
uses: ./.github/workflows/maven-release.yml
15+
with:
16+
java-version: '21'
17+
secrets:
18+
DEPS_TOKEN: ${{ secrets.DEPS_TOKEN }}

0 commit comments

Comments
 (0)