Reusable Forgejo Actions for Revenge Next plugins and releases
  • Shell 46.7%
  • JavaScript 28.4%
  • Python 24.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Rosie 52a4738903
Some checks failed
Validate actions / manifests (push) Has been cancelled
Validate actions / publish-logic (push) Has been cancelled
build-plugins: support local bun generate-index
2026-10-18 13:14:36 -04:00
.forgejo/workflows fix: work in an image that ships no git 2026-09-27 11:46:40 +02:00
build-plugins build-plugins: support local bun generate-index 2026-10-18 13:14:36 -04:00
checkout-releases fix: accept Forgejo's own token variable, and document what a publish token needs 2026-09-27 12:20:39 +02:00
checkout-repository fix: work in an image that ships no git 2026-09-27 11:46:40 +02:00
publish-releases fix: keep the token out of the log when a push fails 2026-09-27 12:57:55 +02:00
scripts fix: keep the token out of the log when a push fails 2026-09-27 12:57:55 +02:00
setup-android-toolchain fix(setup-android-toolchain): ensure ca-certificates-java generates cacerts when JDK is cached (#1) 2026-10-06 10:20:00 +02:00
setup-bun fix: work in an image that ships no git 2026-09-27 11:46:40 +02:00
setup-node fix: unpack node into the install directory instead of copying its parts 2026-09-27 11:54:15 +02:00
setup-plugin-deps feat: shared Forgejo actions for building and releasing Revenge plugins 2026-09-27 11:31:57 +02:00
templates fix: accept Forgejo's own token variable, and document what a publish token needs 2026-09-27 12:20:39 +02:00
.gitignore fix: export the SDK location, and stop tracking compiled python 2026-09-27 12:06:10 +02:00
LICENSE feat: shared Forgejo actions for building and releasing Revenge plugins 2026-09-27 11:31:57 +02:00
README.md fix: accept Forgejo's own token variable, and document what a publish token needs 2026-09-27 12:20:39 +02:00

RNDUP Shared Actions

Reusable Forgejo Actions for the repositories in the RNDUP organization: building Revenge Next plugins and publishing the result into a shared releases repository.

Nothing in here is specific to one plugin repository. If a repository needs the same CI logic twice, it belongs here instead.

How a release works

push to main
   │
   ├── checkout-repository      clone the exact commit that was pushed
   ├── setup-android-toolchain  Temurin JDK, Android SDK, licences
   ├── setup-bun                JS runtime
   ├── setup-plugin-deps        JS dependencies, plugin CLI, Revenge API -> ~/.m2
   ├── checkout-releases        clone RNDUP/releases into dist/
   ├── (your repository)        anything that has to exist before compilation
   ├── build-plugins            dist/<id>@<version>.zip, dist/index.json, companion APK
   └── publish-releases         commit dist/ and push it to RNDUP/releases

dist/ is a clone of the releases repository, so the build output is the published tree. The clone has to be made before the build: the build writes into it, and a checkout afterwards would overwrite fresh artifacts with the previously published ones.

Because the artifacts land in a separate repository, one organization's plugins can be served from a single index, and a repository can be renamed or moved without invalidating any download URL.

Actions

Action Kind What it does
checkout-repository composite Forgejo does not check anything out for you. Installs git if the image has none, then clones the commit the run was triggered for, authenticated, with safe.directory set.
setup-android-toolchain composite Installs a Temurin JDK and Android SDK (platforms, build-tools, licences) and exports JAVA_HOME, ANDROID_HOME, PATH.
setup-node composite Installs the Node.js runtime that JavaScript actions such as actions/cache are executed with. Leaves an image that already has the right version alone.
setup-bun composite Installs Bun and puts it on PATH. Installs curl first if the image has none.
setup-plugin-deps composite bun install, builds @revenge-mod/plugin-cli from source, publishes io.github.revenge:api to the local Maven repository.
checkout-releases composite Clones the shared releases repository into dist/, creating the branch if it does not exist yet.
build-plugins composite Builds and packages every plugin, generates index.json, verifies the artifacts are readable.
publish-releases node20 Commits the artifacts in the releases clone, pushes, optionally prunes superseded ones and mirrors the tree to a Pages branch.

Using them in your own repository

Cross instance references need the full URL. A bare owner/repo/path@ref is resolved against the marketplace instance (github.com), not against git.gay, so uses: RNDUP/Shared-Actions/... does not work here.

- uses: https://git.gay/RNDUP/Shared-Actions/build-plugins@v1
  with:
    base-url: https://example.org/plugins

Any repository on git.gay can use these, as long as its Actions are enabled and a token it can authenticate with may write to the releases repository.

The automatic workflow token is not that token. It is minted for the repository the workflow runs in and is scoped to it, so it cannot write to a separate releases repository — not even inside the same organization, and granting the runner user more access does not change it:

This token can only be used for interactions with the repository it was created for. — Forgejo Actions | Security

So publishing always needs an explicit token. Mint one under a user that may write to the releases repository: Settings → Applications → Generate New Token, scope write:repository, and set Repository access to Specific repositories listing only the repositories that token may touch. Store it as a secret and pass it to both actions — checkout-releases needs it to clone privately, and publish-releases to push:

- uses: https://git.gay/RNDUP/Shared-Actions/checkout-releases@v1
  with:
    token: ${{ secrets.PUBLISH_TOKEN }}

- uses: https://git.gay/RNDUP/Shared-Actions/publish-releases@v1
  with:
    token: ${{ secrets.PUBLISH_TOKEN }}

One credential covers every push the job makes. If you mirror with mirror-to-repository, add that repository to the token's list as well, because the mirror is pushed with the same token.

A token belongs to the account that minted it, so prefer a dedicated machine user over your own: the pushes stop depending on a person, and the token can be rotated without touching a human account.

A complete working example is in templates/plugin-release.yml.

The container image needs nothing prepared in advance. checkout-repository is normally the first step of a job and cannot rely on an earlier step having installed anything, so it installs git itself when the image has none (apt, apk, dnf or yum). The same goes for setup-node, which installs the Node.js that actions/cache is executed with, and for setup-bun, which needs curl. A plain ubuntu:22.04 therefore works as it is.

Pinning

@v1 is a tag that always points at the newest commit of the v1 line, which keeps consumers working while changes stay opt in. If you need a build that cannot change under you, pin a commit instead:

- uses: https://git.gay/RNDUP/Shared-Actions/build-plugins@<sha>

What every repository still has to do itself

  • .gitignore must contain dist/. checkout-releases warns when it does not, because a nested clone that gets committed turns the next checkout into a conflict.
  • Secrets stay in the repository that owns them. The passkey injection of kmmiio99o-plugins is deliberately an inline step: the value never passes through a shared action, and AGENTS.md in that repository forbids moving it. Shared actions take build inputs, not credentials that decide what a build contains.
  • The base-url is yours to choose. It is the URL the artifacts will be served from. It has to be the releases repository, not the source repository, or every download link in index.json 404s.

Serving the releases

publish-releases can mirror the published tree onto a branch of your own repository:

with:
  mirror-to-repository: RNDUP/kmmiio99o-plugins
  mirror-to-branch: gh-pages

That keeps an already configured Pages domain working without moving DNS, while the releases repository stays the single source of truth. To serve RNDUP/releases directly instead, enable Pages for it and point the domain there; the mirror is then unnecessary.

Developing

Validate every action and workflow after a change:

python3 scripts/validate-actions.py .

Run a composite action's steps locally, with the same INPUT_* variables a runner would set:

python3 scripts/run-composite.py setup-android-toolchain/action.yml "Install Android SDK components"

publish-releases is a plain Node script with no dependencies, so it can be exercised against a throwaway repository:

git init --bare -b main /tmp/remote.git
mkdir -p /tmp/work/dist && git -C /tmp/work/dist init -q -b main
INPUT_DIST_DIR=/tmp/work/dist INPUT_PRUNE=true node publish-releases/publish.js

dry-run: 'true' reports what would be committed without pushing and leaves the clone in its original state.