Switch to composite actions (Forgejo 11 lacks workflow_call)

This commit is contained in:
Noah Holt 2026-08-10 21:48:08 -05:00
parent 46bcafb9cb
commit 753a3b37de
6 changed files with 141 additions and 118 deletions

View file

@ -1,88 +0,0 @@
# Reusable, language-agnostic build->push->deploy workflow. The app's
# Dockerfile owns the toolchain; this only needs docker + git + kustomize,
# which the `host` runner label provides (see the homelab repo's
# nixos/hosts/forgejo/default.nix hostPackages).
#
# Consumers:
# jobs:
# deploy:
# uses: nholtware/workflows/.forgejo/workflows/build-and-deploy.yaml@main
# with: { app-name: my-app }
# secrets: inherit
#
# Required Actions secrets (set once at user/org level):
# REGISTRY_USER / REGISTRY_TOKEN -- Forgejo PAT with write:package
# GITOPS_TOKEN -- Forgejo PAT with write access to the gitops repo
on:
workflow_call:
inputs:
app-name:
required: true
type: string
context:
required: false
type: string
default: "."
dockerfile:
required: false
type: string
default: "Dockerfile"
gitops-repo:
required: false
type: string
default: "nholtware/gitops"
secrets:
REGISTRY_USER:
required: true
REGISTRY_TOKEN:
required: true
GITOPS_TOKEN:
required: true
env:
# Terraform-pinned static IP of the forgejo host; containerd on the k3s
# nodes trusts exactly this registry string (nixos/modules/k3s-registries.nix).
REGISTRY: 192.168.1.230:3000
jobs:
build-push:
runs-on: host
steps:
- uses: actions/checkout@v4
- name: Log in to Forgejo registry
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin
- name: Build and push image
run: |
TAG=$(echo "$GITHUB_SHA" | cut -c1-8)
IMAGE="$REGISTRY/${{ github.repository_owner }}/${{ inputs.app-name }}"
docker build -f "${{ inputs.dockerfile }}" \
--build-arg GIT_SHA="$TAG" \
-t "$IMAGE:$TAG" -t "$IMAGE:latest" "${{ inputs.context }}"
docker push "$IMAGE:$TAG"
docker push "$IMAGE:latest"
bump-gitops:
needs: build-push
runs-on: host
steps:
- name: Update image tag in gitops repo
env:
GITOPS_TOKEN: ${{ secrets.GITOPS_TOKEN }}
run: |
TAG=$(echo "$GITHUB_SHA" | cut -c1-8)
IMAGE="$REGISTRY/${{ github.repository_owner }}/${{ inputs.app-name }}"
rm -rf gitops
git clone "http://ci-bot:${GITOPS_TOKEN}@192.168.1.230:3000/${{ inputs.gitops-repo }}.git" gitops
cd "gitops/manifests/${{ inputs.app-name }}"
kustomize edit set image "${{ inputs.app-name }}=$IMAGE:$TAG"
cd ../..
git config user.name "ci-bot"
git config user.email "ci-bot@forgejo.local"
git add -A
git commit -m "${{ inputs.app-name }}: deploy $TAG" || echo "no change to commit"
git push

View file

@ -1,21 +0,0 @@
# Reusable Node/TypeScript checks: install, lint (if present), test (if
# present). Runs in the docker-label container (node preinstalled).
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: "22"
jobs:
checks:
runs-on: docker
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm run lint --if-present
- run: npm test --if-present

View file

@ -1,13 +1,44 @@
# workflows
Reusable Forgejo Actions workflows for the homelab pipeline.
Shared composite actions for the homelab CI/CD pipeline. (Composite
actions, not reusable workflows: Forgejo LTS 11 does not support
`on: workflow_call`.)
- `build-and-deploy.yaml` — language-agnostic: docker build -> push to the
Forgejo registry (`192.168.1.230:3000`) -> bump the image tag in
`nholtware/gitops` (ArgoCD takes it from there). Inputs: `app-name`
(required), `context`, `dockerfile`, `gitops-repo`.
- `node-checks.yaml` — optional TypeScript/Node checks: `npm ci`, lint,
test (each `--if-present`).
- `node-checks` — npm ci + lint + test (each `--if-present`)
- `build-push` — docker build + push to the Forgejo registry
(`192.168.1.230:3000`), tags `<short-sha>` + `latest`
- `gitops-bump` — set the image tag in `nholtware/gitops` via
`kustomize edit set image`; ArgoCD deploys from there
Secrets expected (user/org-level Actions secrets): `REGISTRY_USER`,
`REGISTRY_TOKEN` (write:package), `GITOPS_TOKEN` (write to gitops repo).
A consuming app's `.forgejo/workflows/ci.yaml` (see nholtware/demo-app):
```yaml
on:
push:
branches: [main]
jobs:
checks:
runs-on: docker
steps:
- uses: actions/checkout@v4
- uses: http://192.168.1.230:3000/nholtware/workflows/node-checks@main
deploy:
needs: checks
runs-on: host
steps:
- uses: actions/checkout@v4
- uses: http://192.168.1.230:3000/nholtware/workflows/build-push@main
with:
app-name: my-app
registry-user: ${{ secrets.REGISTRY_USER }}
registry-token: ${{ secrets.REGISTRY_TOKEN }}
- uses: http://192.168.1.230:3000/nholtware/workflows/gitops-bump@main
with:
app-name: my-app
gitops-token: ${{ secrets.GITOPS_TOKEN }}
```
Secrets are user-level Actions secrets on the repo owner: `REGISTRY_USER`,
`REGISTRY_TOKEN` (write:package), `GITOPS_TOKEN` (write on the gitops repo).
For a non-Node app, drop the `checks` job (or swap in your own) — `deploy`
is language-agnostic.

47
build-push/action.yaml Normal file
View file

@ -0,0 +1,47 @@
name: build-push
description: >
Language-agnostic image build + push to the homelab Forgejo registry.
The app's Dockerfile owns the toolchain. Run after actions/checkout, on
the `host` runner label (host docker daemon has the insecure-registry
config -- see homelab nixos/hosts/forgejo/default.nix). Tags pushed:
<short-sha> and latest.
inputs:
app-name:
description: Image name (registry path is <registry>/<owner>/<app-name>)
required: true
context:
description: Docker build context
required: false
default: "."
dockerfile:
description: Path to Dockerfile
required: false
default: Dockerfile
registry:
description: Registry host:port
required: false
default: "192.168.1.230:3000"
registry-user:
description: Registry login user (pass secrets.REGISTRY_USER)
required: true
registry-token:
description: Registry token, write:package scope (pass secrets.REGISTRY_TOKEN)
required: true
runs:
using: composite
steps:
- shell: bash
env:
REGISTRY: ${{ inputs.registry }}
REGISTRY_USER: ${{ inputs.registry-user }}
REGISTRY_TOKEN: ${{ inputs.registry-token }}
run: |
set -euo pipefail
TAG="${GITHUB_SHA:0:8}"
IMAGE="$REGISTRY/$GITHUB_REPOSITORY_OWNER/${{ inputs.app-name }}"
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" -u "$REGISTRY_USER" --password-stdin
docker build -f "${{ inputs.dockerfile }}" \
--build-arg GIT_SHA="$TAG" \
-t "$IMAGE:$TAG" -t "$IMAGE:latest" "${{ inputs.context }}"
docker push "$IMAGE:$TAG"
docker push "$IMAGE:latest"

40
gitops-bump/action.yaml Normal file
View file

@ -0,0 +1,40 @@
name: gitops-bump
description: >
Points the app's kustomize overlay in the gitops repo at the image tag
just pushed (short sha of the triggering commit); ArgoCD picks up the
commit and deploys. Run on the `host` runner label (git + kustomize
installed there).
inputs:
app-name:
description: App name (dir under manifests/ and kustomize image name)
required: true
gitops-repo:
description: owner/name of the gitops repo
required: false
default: nholtware/gitops
gitops-token:
description: Token with write access to the gitops repo (pass secrets.GITOPS_TOKEN)
required: true
registry:
description: Registry host:port (must match build-push)
required: false
default: "192.168.1.230:3000"
runs:
using: composite
steps:
- shell: bash
env:
GITOPS_TOKEN: ${{ inputs.gitops-token }}
run: |
set -euo pipefail
TAG="${GITHUB_SHA:0:8}"
IMAGE="${{ inputs.registry }}/$GITHUB_REPOSITORY_OWNER/${{ inputs.app-name }}"
DIR="$(mktemp -d)"
trap 'rm -rf "$DIR"' EXIT
git clone --depth 1 "http://ci-bot:${GITOPS_TOKEN}@192.168.1.230:3000/${{ inputs.gitops-repo }}.git" "$DIR"
cd "$DIR/manifests/${{ inputs.app-name }}"
kustomize edit set image "${{ inputs.app-name }}=$IMAGE:$TAG"
cd "$DIR"
git -c user.name=ci-bot -c user.email=ci-bot@forgejo.local \
commit -am "${{ inputs.app-name }}: deploy $TAG" || { echo "tag unchanged, nothing to deploy"; exit 0; }
git push

14
node-checks/action.yaml Normal file
View file

@ -0,0 +1,14 @@
name: node-checks
description: >
Node/TypeScript checks: npm ci, then lint and test if the package defines
them. Run after actions/checkout, in a job with node available (the
homelab runner's `docker` label image has it).
runs:
using: composite
steps:
- run: npm ci
shell: bash
- run: npm run lint --if-present
shell: bash
- run: npm test --if-present
shell: bash