Files
pipeline-actions/AGENTS.md

7.2 KiB

pipeline-actions — Agent Guide

Overview

This repo provides reusable Gitea composite actions for homelab CI/CD pipelines. Actions are consumed by other projects via the full-URL form uses: https://git.ivanch.me/ivanch/pipeline-actions/<action>@main.

Actions

build-and-push (build-and-push/action.yaml)

Logs into the container registry, sets up SSH key for docker-build.haven, creates a remote Buildx context over SSH, and builds + pushes a multi-arch Docker image.

Inputs:

  • image (required) — full image ref without tag
  • registry_password (required) — registry password/token (use secrets)
  • ssh_key (required) — SSH private key for remote builder (use secrets)
  • image_tag (default latest) — comma-separated tag(s) to apply to the built image (e.g. latest,abc1234)
  • registry_host (default git.ivanch.me) — container registry hostname
  • registry_username (default ivanch) — registry username
  • platforms (default linux/amd64,linux/arm64) — target build platforms
  • build_context (default .) — Docker build context path
  • build_dockerfile (default Dockerfile) — Dockerfile path relative to context
  • build_args (default empty) — build arguments, one KEY=VALUE per line; each becomes a --build-arg
  • docker_host (default docker-build.haven) — remote builder hostname
  • docker_user (default root) — SSH user for remote builder

deploy-restart (deploy-restart/action.yaml)

Validates KUBE_CONFIG, installs kubectl, and performs rollout restart of a Kubernetes Deployment.

Inputs:

  • kube_config (required) — full kubeconfig YAML (use secrets)
  • deployment_name (required) — Deployment name to restart
  • namespace (default default) — Kubernetes namespace
  • kube_version (default stable) — kubectl version to download

kubectl-apply (kubectl-apply/action.yaml)

Validates KUBE_CONFIG, installs kubectl, and applies Kubernetes manifest(s) that live inside the repository. This is the in-repo, k8s analog of ssh-deploy's compose_files, and the recommended way to deploy manifest specs committed to the consuming repo. Pair it with deploy-restart when a restart is also required (Deployments); use it alone for CronJobs, Services, Ingresses, Secrets, etc.

Inputs:

  • kube_config (required) — full kubeconfig YAML (use secrets)
  • manifest (default empty) — single manifest path (relative to repo root) to apply
  • manifests (default empty) — space-/comma-separated list of manifest paths; each applied with its own kubectl apply -f
  • namespace (default empty) — adds -n <ns> when non-empty (manifests may also self-declare their namespace)
  • kube_version (default stable) — kubectl version to download

At least one of manifest/manifests must be set. A path that does not exist in the repo fails the step — the manifest must be committed to the repo.

ssh-deploy (ssh-deploy/action.yaml)

SSH into a remote host, pull the latest images with docker compose pull, and recreate containers with docker compose up -d --force-recreate. Uses native ssh/ssh-keyscan — no third-party SSH action.

Inputs:

  • ssh_host (required) — remote server hostname or IP
  • ssh_username (required) — SSH username
  • ssh_key (required) — SSH private key (use secrets)
  • remote_dir (required) — directory on the remote server containing docker-compose.yml
  • ssh_port (default 22) — SSH port
  • compose_files (default empty) — space-separated compose file paths (applied via -f flags)
  • image (default empty) — image base (host/path/name, no tag); when set, every compose service matching this base is pinned to image_tag at deploy time
  • image_tag (default latest) — tag applied to image when set (single tag; no comma-lists)

Workflow Template for New Projects

When wiring up CI/CD for a new homelab project, create .gitea/workflows/main.yaml:

name: Build and Deploy (internal)

on:
  push:
    branches:
      - main
  workflow_dispatch: {}

env:
  IMAGE: git.ivanch.me/ivanch/<PROJECT_NAME>

jobs:
  build:
    name: Build Image
    runs-on: ubuntu-amd64
    steps:
      - uses: actions/checkout@v4
      - uses: https://git.ivanch.me/ivanch/pipeline-actions/build-and-push@main
        with:
          image: ${{ env.IMAGE }}
          registry_password: ${{ secrets.REGISTRY_PASSWORD }}
          ssh_key: ${{ secrets.SSH_KEY_DOCKERBUILD }}

  deploy:
    name: Deploy (internal)
    runs-on: ubuntu-amd64
    needs: build
    steps:
      # Deployment specs live in the repo; apply them with kubectl-apply.
      - uses: https://git.ivanch.me/ivanch/pipeline-actions/kubectl-apply@main
        with:
          kube_config: ${{ secrets.KUBE_CONFIG }}
          manifest: deploy/<PROJECT_NAME>.yaml
      # Restart the Deployment so the new image is rolled out.
      - uses: https://git.ivanch.me/ivanch/pipeline-actions/deploy-restart@main
        with:
          kube_config: ${{ secrets.KUBE_CONFIG }}
          deployment_name: <DEPLOYMENT_NAME>
          namespace: <NAMESPACE>

Required Secrets

Consumer projects must set these secrets in Gitea repo settings (Settings → Actions → Secrets):

Secret Purpose
REGISTRY_PASSWORD Container registry password/token for git.ivanch.me
SSH_KEY_DOCKERBUILD SSH private key for root@docker-build.haven
KUBE_CONFIG Full kubeconfig YAML for k8s cluster access
DEPLOY_HOST Remote server hostname or IP (for ssh-deploy)
DEPLOY_USERNAME SSH username for the remote server (for ssh-deploy)
DEPLOY_KEY SSH private key for the remote server (for ssh-deploy)
DEPLOY_DIR Directory on the remote server with docker-compose.yml (for ssh-deploy)

Rules

  • Pin composite action refs to @main until version tags are created.
  • Every job must have a name: field (e.g. name: Build Image, name: Deploy (internal)). Unnamed jobs render as their raw ID (build, deploy, …) in the Gitea Actions UI and run logs. The workflow template above includes name: on every job — copy it as-is.
  • Always use the full URL https://git.ivanch.me/ivanch/pipeline-actions/<action>@main for uses: — Gitea cannot resolve the bare GitHub-style ivanch/pipeline-actions/... path.
  • Always use runs-on: ubuntu-amd64 (homelab Gitea runner label).
  • Always build linux/amd64,linux/arm64 — the cluster has mixed arch (iris+vega=amd64, nebula+nexus=arm64).
  • Workflow files go in .gitea/workflows/main.yaml of the consuming project.
  • The consuming project must have a working Dockerfile at the repo root (or pass build_dockerfile input).
  • Kubernetes deploy specs are committed to the consuming repo (e.g. under */deploy/*.yaml) and applied with kubectl-apply. Pass their repo-relative path via manifest/manifests. Do not write deploy specs inline in the workflow — they belong in the repo so they can be reviewed and versioned.

Do Not

  • Do not add GitHub Actions workflows — these are Gitea composite actions only.
  • Do not hardcode secrets in workflow files — always use ${{ secrets.* }}.
  • Do not override platforms to a single arch unless there's a specific reason.
  • Do not vendor dependencies — consumers reference this repo via the full-URL uses: form.