mirror of
https://github.com/horizon-rust/horizon-mods.git
synced 2026-11-07 02:56:08 -10:00
The registry: coords_hud, the checks, publishing to Pages, the weekly cleanup
- mods/coords_hud.toml: the SDK's example mod, MIT, built from crates/horizon-mod-sdk/examples/coords-hud in Horizon. - check.yml: a pull request's changes, each new file's checks and a trial run in the sandbox, the index it would publish (cargo horizon-mod from Horizon at HORIZON_REV). - publish.yml: on main, new versions become releases, index.json and the icons go to GitHub Pages. - cleanup.yml: staging copies nobody needs, weekly. - CODEOWNERS, the report form, the pull request template, revoked.toml. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
0608babaab
commit
52e1f7d0f9
12 files changed
+326
No files matched your search
@@ -0,0 +1,5 @@
|
||||
# Every change needs a review from one of these before it merges (branch protection:
|
||||
# "Require review from Code Owners"). Add trusted contributors to the first line.
|
||||
* @ludovic111 @rdbtCVS @levzzz5154 @socksprox
|
||||
/.github/ @ludovic111
|
||||
/revoked.toml @ludovic111
|
||||
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Submit a project
|
||||
url: https://playhorizon.dev/mods/submit
|
||||
about: Mods, modpacks and resource packs for Horizon. Each submission is reviewed.
|
||||
- name: Horizon itself
|
||||
url: https://github.com/ludovic111/horizon/issues
|
||||
about: Bugs in the game or the launcher.
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Report a project
|
||||
description: Something in the registry does harm, breaks the game, isn't what it says, or isn't its author's to publish.
|
||||
title: "Report: "
|
||||
labels: [report]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks. Reviewers read every report. If it is dangerous (it deletes files, steals
|
||||
accounts, spreads), say so in the first line: it can be taken down within hours, and
|
||||
the launcher then turns installed copies off. Bugs in a mod go to its source repository.
|
||||
- type: input
|
||||
id: project
|
||||
attributes:
|
||||
label: Project id
|
||||
description: The last part of its page's address, playhorizon.dev/mods/<id>
|
||||
placeholder: coords_hud
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
placeholder: 0.1.0, or "all"
|
||||
- type: dropdown
|
||||
id: why
|
||||
attributes:
|
||||
label: What is wrong
|
||||
options:
|
||||
- It does harm (files, accounts, chat it shouldn't send, anything malicious)
|
||||
- It isn't what its page says
|
||||
- It breaks the game or other mods
|
||||
- It isn't the submitter's to publish (copyright, licence, stolen)
|
||||
- Something else
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: What happened
|
||||
description: Steps, what you saw, and logs if you have them (the game's log is latest.log in its folder).
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,9 @@
|
||||
<!-- Changing mods/<id>.toml by hand? The form at https://playhorizon.dev/mods/submit does this for you. -->
|
||||
|
||||
**Project:** <!-- id, and new project or update -->
|
||||
|
||||
- [ ] I made it, or I am allowed to publish it, under the licence the entry names.
|
||||
- [ ] The `source` link has the code this file was built from.
|
||||
- [ ] I ran `cargo horizon-mod check <file>` and it passed.
|
||||
|
||||
The file goes in the `staging` release as `<sha256>.<extension>` (the form uploads it; by hand, ask a reviewer).
|
||||
@@ -0,0 +1,82 @@
|
||||
# A pull request's checks: what it changes compared with main, each new file's
|
||||
# own check (its kind's, its signature, a trial run of a mod in the sandbox), and
|
||||
# the index it would publish. Runs with a read-only token and no secrets; the tool
|
||||
# comes from Horizon, never from the pull request, and a submission's code only
|
||||
# runs inside Horizon's mod sandbox.
|
||||
name: check
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
group: check-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
HORIZON_REV: ${{ vars.HORIZON_REV || 'main' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
path: base
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
path: head
|
||||
persist-credentials: false
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin
|
||||
~/.cargo/horizon-rev
|
||||
key: cargo-horizon-mod-${{ env.HORIZON_REV }}
|
||||
# main's scripts, not the pull request's.
|
||||
- run: base/scripts/install-tool.sh
|
||||
- name: Who submitted it
|
||||
id: author
|
||||
env:
|
||||
LOGIN: ${{ github.event.pull_request.user.login }}
|
||||
BODY: ${{ github.event.pull_request.body }}
|
||||
BOT: ${{ vars.REGISTRY_BOT || 'horizon-mods-bot' }}
|
||||
run: |
|
||||
# The submission form opens pull requests as the bot and names the
|
||||
# GitHub account that signed in to it.
|
||||
author="$LOGIN"
|
||||
if [ "$LOGIN" = "$BOT" ] || [ "$LOGIN" = "${BOT}[bot]" ]; then
|
||||
author="$(printf '%s' "$BODY" | sed -n 's/.*<!-- submitted-by: \([A-Za-z0-9-]*\) -->.*/\1/p' | head -1)"
|
||||
fi
|
||||
echo "login=${author:-$LOGIN}" >> "$GITHUB_OUTPUT"
|
||||
- name: What it changes
|
||||
run: |
|
||||
set -o pipefail
|
||||
{ echo "## Changes"; echo '```'; } >> "$GITHUB_STEP_SUMMARY"
|
||||
status=0
|
||||
cargo horizon-mod registry review base head --author "${{ steps.author.outputs.login }}" 2>&1 \
|
||||
| tee -a "$GITHUB_STEP_SUMMARY" || status=1
|
||||
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
||||
exit $status
|
||||
- name: Download its files
|
||||
run: base/scripts/fetch.sh head
|
||||
- name: Check each new file
|
||||
run: |
|
||||
set -o pipefail
|
||||
{ echo "## New files"; echo '```'; } >> "$GITHUB_STEP_SUMMARY"
|
||||
status=0
|
||||
cargo horizon-mod registry check base head --files files 2>&1 | tee -a "$GITHUB_STEP_SUMMARY" || status=1
|
||||
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
||||
exit $status
|
||||
- name: The index it would publish
|
||||
run: |
|
||||
cargo horizon-mod registry build head --files files --out index.json --generated "$(date -u +%FT%TZ)"
|
||||
python3 - >> "$GITHUB_STEP_SUMMARY" <<'PY'
|
||||
import json
|
||||
index = json.load(open("index.json"))
|
||||
print("## index.json")
|
||||
for p in index["projects"]:
|
||||
print(f"- {p['kind']} `{p['id']}` {p['versions'][0]['version']}")
|
||||
PY
|
||||
@@ -0,0 +1,43 @@
|
||||
# The submission form uploads files to the `staging` prerelease as
|
||||
# <sha256>.<extension>. Once a version is published in its own release, or when
|
||||
# no open pull request lists a file any more, its staging copy goes:
|
||||
# published ones after 7 days, abandoned ones after 30.
|
||||
name: cleanup
|
||||
on:
|
||||
schedule:
|
||||
- cron: "17 4 * * 1"
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: read
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Delete staging files nobody needs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Hashes main lists (published), and those open pull requests add.
|
||||
grep -ho 'sha256 = "[0-9a-f]\{64\}"' mods/*.toml | cut -d'"' -f2 | sort -u > published.txt || true
|
||||
: > pending.txt
|
||||
for pr in $(gh pr list --state open --json number --jq '.[].number'); do
|
||||
gh pr diff "$pr" | grep -o '^+sha256 = "[0-9a-f]\{64\}"' | cut -d'"' -f2 >> pending.txt || true
|
||||
done
|
||||
now=$(date +%s)
|
||||
gh api --paginate "repos/$GH_REPO/releases/tags/staging" --jq '.assets[] | [.id, .name, .created_at] | @tsv' |
|
||||
while IFS=$'\t' read -r id name created; do
|
||||
sha="${name%%.*}"
|
||||
age=$(( (now - $(date -d "$created" +%s)) / 86400 ))
|
||||
grep -qx "$sha" pending.txt && continue
|
||||
if grep -qx "$sha" published.txt; then
|
||||
[ "$age" -ge 7 ] || continue
|
||||
else
|
||||
[ "$age" -ge 30 ] || continue
|
||||
fi
|
||||
echo "Deleting $name ($age days)"
|
||||
gh api -X DELETE "repos/$GH_REPO/releases/assets/$id"
|
||||
done
|
||||
@@ -0,0 +1,65 @@
|
||||
# Merging publishes: each new version's file becomes a release asset
|
||||
# (<id>-<version>/<file>), then index.json and the icons go to GitHub Pages
|
||||
# (https://ludovic111.github.io/horizon-mods/index.json), which the launcher and
|
||||
# playhorizon.dev/mods read. Nothing is published if any entry fails its checks.
|
||||
name: publish
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
id-token: write
|
||||
concurrency:
|
||||
group: publish
|
||||
cancel-in-progress: false
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.pages.outputs.page_url }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
HORIZON_REV: ${{ vars.HORIZON_REV || 'main' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin
|
||||
~/.cargo/horizon-rev
|
||||
key: cargo-horizon-mod-${{ env.HORIZON_REV }}
|
||||
- run: scripts/install-tool.sh
|
||||
- run: scripts/fetch.sh .
|
||||
- name: Build the index
|
||||
run: |
|
||||
mkdir -p site
|
||||
cargo horizon-mod registry build . --files files --out site/index.json --generated "$(date -u +%FT%TZ)"
|
||||
- name: Publish new files as releases
|
||||
run: |
|
||||
cargo horizon-mod registry list . | while read -r sha id version file; do
|
||||
tag="$id-$version"
|
||||
gh release view "$tag" >/dev/null 2>&1 && continue
|
||||
dir="$(mktemp -d)"
|
||||
cp "files/$sha" "$dir/$file"
|
||||
gh release create "$tag" "$dir/$file" --title "$id $version" --latest=false \
|
||||
--notes "Reviewed in the registry: mods/$id.toml. SHA-256 $sha."
|
||||
done
|
||||
- name: The site
|
||||
run: |
|
||||
cp -R icons site/icons
|
||||
cat > site/index.html <<'HTML'
|
||||
<!doctype html><meta charset="utf-8"><title>Horizon mods</title>
|
||||
<meta http-equiv="refresh" content="0; url=https://playhorizon.dev/mods">
|
||||
<p><a href="https://playhorizon.dev/mods">playhorizon.dev/mods</a> · <a href="index.json">index.json</a></p>
|
||||
HTML
|
||||
- uses: actions/configure-pages@v5
|
||||
- uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: site
|
||||
- id: pages
|
||||
uses: actions/deploy-pages@v4
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 336 B |
@@ -0,0 +1,26 @@
|
||||
id = "coords_hud"
|
||||
kind = "mod"
|
||||
name = "Coordinates HUD"
|
||||
summary = "Your coordinates, facing and the time of day in a corner of the screen."
|
||||
description = """
|
||||
The SDK's example mod. It draws your block position, the direction you face and the time of day
|
||||
in the top-left corner, every frame.
|
||||
|
||||
- `/where` puts your coordinates and dimension in chat.
|
||||
- `/coords` hides or shows the panel.
|
||||
|
||||
It reads the game (position, health, time), draws on the HUD and writes to chat: nothing else.
|
||||
"""
|
||||
authors = ["Horizon"]
|
||||
owners = ["ludovic111"]
|
||||
license = "MIT"
|
||||
source = "https://github.com/ludovic111/horizon/tree/main/crates/horizon-mod-sdk/examples/coords-hud"
|
||||
icon = "icons/coords_hud.png"
|
||||
|
||||
[[versions]]
|
||||
version = "0.1.0"
|
||||
published = "2026-10-24"
|
||||
game = "26.3"
|
||||
file = "coords_hud-0.1.0.hmod"
|
||||
sha256 = "612335e4e00d638f8b97b6c2f5c718c069c7a13811ba922557c27cb2612daf59"
|
||||
changelog = "First release: the panel, `/where` and `/coords`."
|
||||
@@ -0,0 +1,8 @@
|
||||
# Files taken down. The launcher refuses to install them and turns installed copies off,
|
||||
# showing the reason. One file by its sha256, or every version of an id without one.
|
||||
#
|
||||
# [[revoked]]
|
||||
# id = "some_mod"
|
||||
# sha256 = "..."
|
||||
# reason = "What it did, in one sentence players will read."
|
||||
# date = "2026-10-24"
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# Downloads every file the entries list into files/<sha256>: from its own release
|
||||
# (<id>-<version>) once published, else from the `staging` prerelease, where the
|
||||
# submission form uploads <sha256>.<extension>. Usage: scripts/fetch.sh [checkout]
|
||||
# Needs `gh` (GH_TOKEN) and cargo-horizon-mod. FILES_FROM=<dir> reads <dir>/<file>
|
||||
# instead, for a local trial.
|
||||
set -euo pipefail
|
||||
checkout="${1:-.}"
|
||||
mkdir -p files
|
||||
cargo horizon-mod registry list "$checkout" | while read -r sha id version file; do
|
||||
[ -f "files/$sha" ] && continue
|
||||
ext="${file##*.}"
|
||||
tmp="$(mktemp -d)"
|
||||
if [ -n "${FILES_FROM:-}" ]; then
|
||||
cp "$FILES_FROM/$file" "$tmp/$file"
|
||||
elif gh release download "$id-$version" --pattern "$file" --dir "$tmp" 2>/dev/null; then
|
||||
:
|
||||
elif gh release download staging --pattern "$sha.$ext" --dir "$tmp"; then
|
||||
mv "$tmp/$sha.$ext" "$tmp/$file"
|
||||
else
|
||||
echo "::error::$id $version: $file is neither in release $id-$version nor in staging as $sha.$ext"
|
||||
exit 1
|
||||
fi
|
||||
mv "$tmp/$file" "files/$sha"
|
||||
rmdir "$tmp"
|
||||
done
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Installs cargo-horizon-mod from Horizon at $HORIZON_REV (a commit; the repository
|
||||
# variable HORIZON_REV, else main). The registry's checks are that tool's.
|
||||
set -euo pipefail
|
||||
rev="${HORIZON_REV:-main}"
|
||||
if command -v cargo-horizon-mod >/dev/null && [ "$(cat ~/.cargo/horizon-rev 2>/dev/null)" = "$rev" ]; then
|
||||
exit 0
|
||||
fi
|
||||
cargo install --locked --git https://github.com/ludovic111/horizon --rev "$rev" cargo-horizon-mod 2>/dev/null \
|
||||
|| cargo install --locked --git https://github.com/ludovic111/horizon --branch "$rev" cargo-horizon-mod
|
||||
echo "$rev" > ~/.cargo/horizon-rev
|
||||
Reference in new issue
Block a user