HOIST IT first-party reusable Forgejo composite actions https://www.hoist-it.nl
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-19 10:35:05 +00:00
build-push-sign-images feat(build-push-sign-images): collapsible, coloured, structured logs 2026-07-18 11:27:25 +02:00
docs/images feat: add banner and update readme 2026-07-19 12:33:16 +02:00
forge-checkout chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
gitops-bump-pr chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
LICENSES chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
mirror-repo chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
next-version chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
repo-hygiene chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
setup-nix-flake-auth chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
CODE_OF_CONDUCT.md docs: add CODEOWNERS, SECURITY, CONTRIBUTING and CODE_OF_CONDUCT 2026-07-17 17:45:33 +02:00
CODEOWNERS chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
CONTRIBUTING.md chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
LICENSE.md chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
README.md feat: update readme 2026-07-19 12:34:45 +02:00
REUSE.toml chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00
SECURITY.md chore(license): relicense to Apache-2.0 2026-07-18 11:06:20 +02:00

HOIST IT Data Platform Engine logo

HOIST IT - Forgejo actions

Contributor Covenant License Contact

First-party composite actions shared across HOIST IT repositories.

Reference an action by its full URL and subpath, pinned to a tag:

- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]

Actions

forge-checkout

Blessed checkout for HOIST IT sha256 Forgejo repos. Wraps HOIST-IT-Actions/checkout@v7 with GIT_DEFAULT_HASH=sha256 and an optional exact-SHA reset (full fetch), replacing the per-repo checkout@v6/v7 + code.forgejo.org drift and every re-pasted GIT_DEFAULT_HASH.

input default description
ref (triggering ref) Branch/tag/ref to check out.
fetch-depth 1 Shallow depth (0 = full). Forced to 0 when sha is set.
sha (none) Exact commit SHA to reset the worktree to after checkout.
- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  with:
    sha: ${{ github.sha }}

setup-nix-flake-auth

Authenticate nix's flake fetcher against the private forge so a repo can pull a private git+forge flake input (for example the toolbox). nix uses libgit2, which ignores git's url.insteadOf but does consult git's credential helper, so the token is stored in ~/.git-credentials (never in argv or the locked flake URL). Pass the token as an input; the caller supplies it from a secret.

input default description
forge-token (required) Forgejo token with read access to the private flake-input repo(s).
host forge.hoist-it.nl Forge host the credential is scoped to.
- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  with:
    forge-token: ${{ secrets.FORGE_TOKEN }}

next-version

Compute the next semver from the conventional-commit history with commitizen (read-only, no bump/commit/tag). Outputs version and release; release is false when there are no releasable commits since the last tag, gating the build/publish/tag jobs into a no-op. Needs uvx on PATH and a full-depth checkout with tags.

input default description
commitizen-spec commitizen>=4.16 pip requirement spec for commitizen.
- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  id: ver
- run: echo "release=${{ steps.ver.outputs.release }} version=${{ steps.ver.outputs.version }}"

repo-hygiene

Server-side hygiene gate: actionlint over the workflow files plus gitleaks over the full history. Self-provisions both tools from a pinned nixpkgs (no version drift), so it needs nix on the job (run it on a nix-capable image). gitleaks needs a full-depth checkout.

input default description
actionlint-config .github/actionlint.yaml actionlint ignore-list; skipped if absent.
gitleaks-args detect --source . --verbose --redact gitleaks arguments.
nixpkgs (pinned rev) nixpkgs providing actionlint + gitleaks.
- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]

gitops-bump-pr

Open a GitOps deploy PR: clone the gitops repo, bump the newTag of an image in a kustomization, commit on a branch, push, and open a PR. Needs git, curl and jq on PATH.

input default description
gitops-repo (required) owner/repo of the gitops repository.
kustomization (required) Path (in the gitops repo) to the kustomization to bump.
image-tag (required) New tag to set as newTag.
token (required) Token with write access to the gitops repo.
host forge.hoist-it.nl Forge host.
base main Base branch to target.
- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  with:
    gitops-repo: HOISTIT/gitops
    kustomization: apps/staging/website/kustomization.yaml
    image-tag: ${{ needs.build.outputs.tag }}
    token: ${{ secrets.GITOPS_TOKEN }}

mirror-repo

Mirror the checked-out repo to one or more external remotes, optionally converting a SHA-256 repo to SHA-1 first. Needs a full-depth checkout and a recent git (the nix-ci / node-ci images carry git 2.54).

input default description
dst-urls (required) Destination remote URLs (with creds), space- or newline-separated.
convert-sha256-to-sha1 false Convert a SHA-256 source to SHA-1 before mirroring.
- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  with:
    dst-urls: ${{ secrets.CLIENT_MIRROR_URL }}
    convert-sha256-to-sha1: "true"

build-push-sign-images

Build every nix2container image from a flake, push it daemonlessly (skopeo copyTo), and cosign-sign plus attest it, under strict runner-disk discipline: an upfront nix store gc, a gc-rooted signing toolchain, and a per-image nix store gc when free store space drops below a threshold. Each image builds, pushes and signs independently (a failure is recorded and the loop continues), then the run exits non-zero if any image failed (fail-closed). Extracted from toolbox build-images.yaml so the disk-GC discipline and the fail-closed loop live in one place. The calling job owns the container, the flake checkout and the registry/cosign secrets; the action owns the loop and the disk discipline. Run it on a nix-capable image (nixos-nix / nix-ci) whose NIX_CONFIG enables nix-command + flakes and sets sandbox = false.

Two modes cover the two flake-app shapes in use across the org:

  • copyto-sign (default, the toolbox shape): per image name, push via <flake>#<name>.copyTo then sign via <flake>#<sign-app> -- <name>.
  • publish-app (the dp-engine / mkPublishImage shape): per target, run one self-contained build+push+sign app as <flake>#<app> -- <dest-ref>:<tag>.
input default description
mode copyto-sign copyto-sign or publish-app.
flake . Flake ref prefix for nix run/nix eval; sha256 repos pass path:..
tag latest Tag to push. publish-app appends it to each dest-ref; copyto-sign's sign-image pins :latest itself, so keep latest there (see caveats).
registry forge.hoist-it.nl/hoist-it-infra Base registry+namespace for copyto-sign pushes.
images (enumerated) copyto-sign: explicit names; enumerated from images-expr when empty.
images-expr .#ciImageNames copyto-sign: nix expr evaluated to a JSON list of names.
sign true copyto-sign: sign each pushed image.
sign-app sign-image copyto-sign: the signing flake app (<flake>#<sign-app> -- <name>).
apps (none) publish-app: newline list of <app> <dest-ref> targets.
gc-root-app (none) Flake app to gc-root before the loop (toolbox passes sign-image).
gc-threshold-gib 15 Per-image nix store gc below this many GiB free (0 disables; see caveats).
store-path /nix Filesystem whose free space bounds the per-image gc.
working-directory . Directory the loop runs in (where the flake lives); consumers cloning into a temp dir point this at it.
log-groups true Wrap each phase in a collapsible ::group:: and print a coloured summary; false for flat output.

Per-image output is wrapped in a collapsible log group and coloured (honours NO_COLOR): a successful run shows one folded group per image plus a coloured summary, and a failed target re-prints its full log expanded with an ::error::. Set log-groups: false for flat, ungrouped output.

Registry auth: set REGISTRY_USER + REGISTRY_TOKEN in the job env (the action passes them as --dest-creds for copyto-sign), or provide REGISTRY_AUTH_FILE for skopeo. Signing reads the COSIGN_* env the flake apps expect. Set all of these on the calling job.

Two caveats:

  • copyto-sign's sign-app derives its own reference. The bundled sign-image signs <default registry>/<img>:latest, so keep tag: latest and the default registry in copyto-sign mode unless you pass a sign-app that signs the pushed <registry>/<img>:<tag> (a non-latest tag would otherwise sign the old :latest digest; the action warns when it detects this).
  • publish-app apps that SHARE an unrooted build-time toolchain across iterations (dp-engine's two apps reuse a just-built, unrooted skopeo) must set gc-threshold-gib: "0", so the per-image gc does not reclaim that toolchain and force a recompile that exhausts the runner disk (#34).

toolbox (copyto-sign, clone into /tmp/tb, enumerate the flake image list, gc-root the shared signer):

- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  with:
    working-directory: /tmp/tb
    gc-root-app: sign-image

dp-engine (publish-app, two self-contained apps, sha256 repo so path:., shared skopeo so the mid-loop gc is disabled):

- uses: https://forge.hoist-it.nl/HOIST-IT-Actions/actions/[email protected]
  with:
    mode: publish-app
    flake: "path:."
    working-directory: /tmp/src
    tag: ${{ needs.bump.outputs.version }}
    gc-threshold-gib: "0"
    apps: |
      release-image ${{ vars.REGISTRY_URL }}/${{ env.IMAGE_NAME }}
      runner-release-image ${{ vars.REGISTRY_URL }}/${{ env.RUNNER_IMAGE_NAME }}