diff --git a/.forgejo/workflows/build-and-deploy.yaml b/.forgejo/workflows/build-and-deploy.yaml deleted file mode 100644 index fa417f4..0000000 --- a/.forgejo/workflows/build-and-deploy.yaml +++ /dev/null @@ -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 diff --git a/.forgejo/workflows/node-checks.yaml b/.forgejo/workflows/node-checks.yaml deleted file mode 100644 index a00d810..0000000 --- a/.forgejo/workflows/node-checks.yaml +++ /dev/null @@ -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 diff --git a/README.md b/README.md index fc7b09a..0a0fd41 100644 --- a/README.md +++ b/README.md @@ -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 `` + `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. diff --git a/build-push/action.yaml b/build-push/action.yaml new file mode 100644 index 0000000..4200c79 --- /dev/null +++ b/build-push/action.yaml @@ -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: + and latest. +inputs: + app-name: + description: Image name (registry path is //) + 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" diff --git a/gitops-bump/action.yaml b/gitops-bump/action.yaml new file mode 100644 index 0000000..efa8209 --- /dev/null +++ b/gitops-bump/action.yaml @@ -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 diff --git a/node-checks/action.yaml b/node-checks/action.yaml new file mode 100644 index 0000000..d4b21be --- /dev/null +++ b/node-checks/action.yaml @@ -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