Compare commits

..

2 commits

Author SHA1 Message Date
MiTHRAL
c3e6de91ff Correct stale packwiz index hashes for kubejs content
Some checks failed
Build & Release Pack / build (push) Failing after 48s
2026-08-19 15:29:31 -04:00
MiTHRAL
167249fcc8 Add Gitea Actions CI/CD workflow for pack build and release
Builds the client pack on the media-server docker runner: refreshes the
packwiz index, runs integrity + download-resolvability checks, exports
Modrinth (.mrpack) and CurseForge (.zip) artifacts, validates the
CurseForge manifest completeness, uploads artifacts, and publishes a
release on v* tags.
2026-08-19 15:29:15 -04:00
3 changed files with 163 additions and 17 deletions

View file

@ -0,0 +1,146 @@
name: Build & Release Pack
on:
push:
branches: [main]
tags: ['v*']
jobs:
build:
runs-on: docker
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Install packwiz
run: go install github.com/packwiz/packwiz@latest
- name: Add packwiz to PATH
run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
- name: Refresh index
working-directory: client_pack
run: packwiz refresh
- name: Integrity check
working-directory: client_pack
run: |
python3 - <<'EOF'
import hashlib, os, re, sys, tomllib
index = tomllib.load(open("index.toml", "rb"))
indexed = {e["file"] for e in index["files"]}
mods = [f for f in os.listdir("mods") if f.endswith(".pw.toml")]
missing = [f for f in mods if f"mods/{f}" not in indexed]
if missing:
print("ERROR: pw.toml files missing from index.toml:", missing)
sys.exit(1)
extra = [f for f in indexed if f.startswith("mods/") and f not in {f"mods/{m}" for m in mods}]
if extra:
print("ERROR: index.toml entries missing from mods/:", extra)
sys.exit(1)
errors = 0
for f in mods:
data = tomllib.load(open(f"mods/{f}", "rb"))
d = data.get("download")
if not d or not d.get("hash"):
print(f"ERROR: {f} missing [download] hash")
errors += 1
continue
if not d.get("url") and not d.get("mode", "").startswith("metadata:"):
print(f"ERROR: {f} missing [download] url or metadata mode")
errors += 1
if d.get("url", "").startswith("http://"):
print(f"ERROR: {f} uses insecure http url")
errors += 1
hf = d.get("hash-format", "sha512")
if not re.fullmatch(r"[0-9a-f]+", d["hash"]):
print(f"ERROR: {f} hash not hex ({hf})")
errors += 1
if errors:
sys.exit(1)
print(f"OK: {len(mods)} mods indexed, all have [download] url or metadata source")
EOF
- name: Sanity grep download URLs
working-directory: client_pack
run: |
python3 - <<'EOF'
import glob, sys, tomllib
bad = []
url_count = 0
meta_count = 0
for f in sorted(glob.glob("mods/*.pw.toml")):
d = tomllib.load(open(f, "rb")).get("download", {})
if d.get("url"):
url_count += 1
elif d.get("mode", "").startswith("metadata:"):
meta_count += 1
else:
bad.append(f)
if bad:
print("ERROR: mods without download.url or metadata mode:")
for f in bad:
print(" " + f)
sys.exit(1)
print(f"OK: {url_count} direct urls + {meta_count} metadata sources = all mods resolvable")
EOF
- name: Export Modrinth pack
working-directory: client_pack
run: packwiz modrinth export -o ../SciCraft-Modrinth.mrpack --restrictDomains=false
- name: Export CurseForge pack
working-directory: client_pack
run: packwiz curseforge export -o ../SciCraft-CurseForge.zip
- name: Validate CurseForge pack completeness
working-directory: client_pack
run: |
python3 - <<'EOF'
import json, os, re, sys, zipfile, tomllib
z = zipfile.ZipFile("../SciCraft-CurseForge.zip")
manifest = json.loads(z.read("manifest.json"))
pids = {f["projectID"] for f in manifest["files"]}
ov = {n.split("overrides/mods/")[1] for n in z.namelist() if n.startswith("overrides/mods/")}
missing = []
for f in os.listdir("mods"):
if not f.endswith(".pw.toml"):
continue
data = tomllib.load(open(f"mods/{f}", "rb"))
if data.get("side") == "server":
continue
fn = data["filename"]
cf = data.get("update", {}).get("curseforge", {}).get("project-id")
if cf:
if cf not in pids:
missing.append(fn)
elif fn not in ov:
missing.append(fn)
if missing:
print("ERROR: mods missing from CurseForge export:", missing)
sys.exit(1)
print(f"OK: CurseForge export complete ({len(pids)} manifest files + {len(ov)} overrides)")
EOF
- name: Upload pack artifacts
uses: actions/upload-artifact@v4
with:
name: scicraft-pack
path: |
SciCraft-Modrinth.mrpack
SciCraft-CurseForge.zip
- name: Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
files: |
SciCraft-Modrinth.mrpack
SciCraft-CurseForge.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -2,7 +2,7 @@ hash-format = "sha256"
[[files]]
file = "kubejs/assets/scicraft/lang/en_us.json"
hash = "a70cab08a74a2c77ca5312960fba6c51dab08d1fd5a6cbe5166987b66a39cb4e"
hash = "d2126d3b09f8048309675d7a9f79776c1b01070c43bd8b3a0caa2f1f7862f3db"
[[files]]
file = "kubejs/assets/scicraft/textures/block/quantum_lattice.png"
@ -26,51 +26,51 @@ hash = "52b18e603aa0eaf9a900159a24fabbe24f594ada7595a26c1265b77701d8e682"
[[files]]
file = "kubejs/client_scripts/01_tooltips.js"
hash = "3f8428b0534849c4deadab3ecfd3087bdf6a6d6b6a4b627d7af11735a6801028"
hash = "fd17cd238e882e6ccaa70a0abbd89391c6a34c2aa602c3053e287c49e7274801"
[[files]]
file = "kubejs/client_scripts/02_jei_info.js"
hash = "3ce61a3cb56d3ef02284f492bcdbb0a61adf1c9e6ad617b6f11c7065346db531"
hash = "92cc5835152e3b0c8bbb9e7ba16877e0dcb148eb96a5fe1e7f5ccc9ad9f6d6c1"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/first_signal.json"
hash = "95baebfb7af606fc07e9a7cb79d6febdd5dd84054f93a6a07bf770ee52a1c321"
hash = "c545af1e4e6dfcf5049ec19d309fe736777b8e322f95f73cf577efd790bb04f0"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/per_spatium.json"
hash = "fa1105e9de8a8670844f06e2b282ff51f1d8f8e12daefbaec873275a1662915c"
hash = "11d22ba106d9f72cdfd4d97a2e6bcc9d0e9f8084e86ef3592dd7404f567db464"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/root.json"
hash = "aba1bda08e8060751022e9cf23838d2af2a0fd8810585f06ff6e87d188c2688e"
hash = "1ed74aab959c8af06a0bacc4d3e4dc59a2218a61f509dd5a43ad1aecae45a003"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/the_answer.json"
hash = "109b345647b946e891dabead57cd8b4b1270d99d17b288afa2fc44070e12fa9a"
hash = "dc3acf6f16aab9b51eca1a971d94a6c1d60988404a6b04bab7a01da34b4ce3a6"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/the_core.json"
hash = "1dc7c6fc6b4f9eb3662ea61d2ea39b7b55d12d1b0123330d69f6ecbd828fa3ba"
hash = "c51854c18a23b66bec553abd334c7ea396211ac862095c0954f7354e271b101b"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/the_lattice.json"
hash = "5a5293806aba5c81bbfacd8c3f35c0bb3e151832cf916ed9696cbd1b5a1a3542"
hash = "889bb2cbd9c310cbe0ca737ac14c265988958d04a38e60aa8c2cfc996dbe248a"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/the_legacy.json"
hash = "bf9db761224b544c57105455673329fb4ed360d2d839af2b38a2201a53c68270"
hash = "eccc19d5d7784c3b1273a27f3211dc87fa3cb33eca9e89e7c73bb3cb9219ca0f"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/the_seal.json"
hash = "4f44df1c2c9c5ad1016eca3bb08196881142aaa3b4a9dc17bfe0d7f8f7996d49"
hash = "3eeb2305818ca2342669fa3eb08df60c0f5dcfe0a2864a637041c44bbfcf1173"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/the_wound.json"
hash = "439d2dc320914b2e3bebd0bccec3f7747f0e5f944d6e3285654e97bb6b2b9b92"
hash = "798548985135eb86cd3dd921d83c7ab184b89427862335ae621cd6c17e70b410"
[[files]]
file = "kubejs/data/scicraft/advancements/protocol/through_the_doors.json"
hash = "3384d50c04049f3a560c3a5b8190d387c4cf017ad04cebd69ba041190b327fa7"
hash = "dd870892bdb8784d8bbbd420ae91cf9d68c7d67bd396949a1c3b2498c9033a42"
[[files]]
file = "kubejs/data/scicraft/loot_tables/protocol/root_reward.json"
@ -78,7 +78,7 @@ hash = "510aaa143b814db531dda8fc094c2d9a5f589c83b23eb174e6301218b58101e3"
[[files]]
file = "kubejs/server_scripts/00_lore.js"
hash = "b13887d3751908dda093ac69b01e63e91d3567d72df92009574fc9eaf618c9a7"
hash = "06303067d63f9f3f3af14cf0b6b69fc92de15be8cace62c4a31515c47df42877"
[[files]]
file = "kubejs/server_scripts/01_corruption_tide.js"
@ -86,7 +86,7 @@ hash = "b6449e6563a7d4c7b9a95abe5b493ab327e57f01c63147a9ecd8126974c4c045"
[[files]]
file = "kubejs/server_scripts/02_events.js"
hash = "dc3ce6421a8514426452d699a80e99e66c6e746c958da54b88a859802f6b85fc"
hash = "2a81b2c232e68bfa8fd45a05802f7a1ae00a3b70da33b1bcf8bbdf873f60dc03"
[[files]]
file = "kubejs/server_scripts/03_recipes_tags.js"
@ -98,7 +98,7 @@ hash = "67f3bf8b9bc1b2e896e88994b7dcbd9608cd745a99163f0466900d01752b53e9"
[[files]]
file = "kubejs/startup_scripts/registry_blocks.js"
hash = "4ebe3f61b7d7add177a6672ff6e31f7511e66050a31852650043cefbbe168aa7"
hash = "cebf0a1d469abfd32c0a114473ee1c4fea3dc2450a7cbf6819c558885a85b157"
[[files]]
file = "mods/3dskinlayers.pw.toml"

View file

@ -6,7 +6,7 @@ pack-format = "packwiz:1.1.0"
[index]
file = "index.toml"
hash-format = "sha256"
hash = "a6f07880065bc17d2c69123cb16732a1b4aff81d9f647184ee20cc65cd85dfce"
hash = "87ba68c4e45f1c6ffac777bdc3668dbcc1fafead32da12693e64ce93393a9e2d"
[versions]
minecraft = "1.21.1"