Reusable Forgejo Actions workflows shared across lhumina_code hero repos (canonical lab release).
Find a file
omarz 27ae53eefc Switch lab-release to a composite action
Gitea 1.22 on this instance does not execute cross-repo reusable workflows
(jobs.<id>.uses) — it creates an empty job that waits for a runner forever.
Reimplement the same release pipeline as a composite action, which act_runner
runs. Callers keep the job-level container block and invoke the action under
steps:.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 14:37:49 +02:00
lab-release Switch lab-release to a composite action 2026-06-17 14:37:49 +02:00
README.md Switch lab-release to a composite action 2026-06-17 14:37:49 +02:00

lhumina_code / actions

Reusable Forgejo Actions shared across lhumina_code hero repos. Edit the release pipeline here, once — every repo that calls it picks up the change when its pinned tag moves.

lab-release — canonical hero release (composite action)

Builds multi-arch static-musl binaries via the prebaked lab-builder image and publishes a rolling per-branch release (latest-<branch>). main = stable, development / integration = pre-release.

Why a composite action and not a reusable workflow? This Gitea instance (1.22) does not execute cross-repo jobs.<id>.uses reusable workflows — it creates an empty job that waits for a runner forever. Composite actions run fine. The cost: the per-repo caller keeps the job-level container: block, and the action's inner steps render as collapsible groups under one step rather than as separate top-level steps. Revisit reusable workflows after a Gitea/Forgejo upgrade.

Use it from a repo

.forgejo/workflows/lab-release.yaml:

name: lab release
on:
  push:
    branches: [main, development, integration]

permissions:
  contents: write

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    runs-on: docker
    container:
      image: forge.ourworld.tf/lhumina_code/lab-builder:latest-${{ github.ref_name }}
      credentials:
        username: hero.releaser
        password: ${{ secrets.FORGE_TOKEN }}
    defaults:
      run:
        shell: bash
    steps:
      - uses: lhumina_code/actions/lab-release@v1
        with:
          forge-token: ${{ secrets.FORGE_TOKEN }}

The branch list, container image, and credentials stay in the caller (job-level config a composite action cannot set). Everything below steps: is centralized.

Inputs

input default when to set it
forge-token — (required) always: ${{ secrets.FORGE_TOKEN }} (composite actions can't read secrets directly)
packages "" → builds --workspace repo has crates that must not be released → pass the list, e.g. hero_os,hero_os_server,hero_os_admin
platforms linux-musl-x86_64,linux-musl-arm64 a repo ships a different target set
run-check "true" skip the cargo check gate
run-test "true" repo has no meaningful unit tests (e.g. hero_lib) → "false"

Example with tweaks (hero_os style):

      - uses: lhumina_code/actions/lab-release@v1
        with:
          forge-token: ${{ secrets.FORGE_TOKEN }}
          packages: hero_os,hero_os_server,hero_os_admin
          run-test: "false"

Versioning

Callers pin a tag (@v1). Push fixes to main, then move the v1 tag forward to roll them out to every repo at once. Cut @v2 only for breaking input changes, so repos can migrate on their own schedule.