commit 4a66d2b26db6a271be355c285b0b755065a0dffe Author: peet Date: Fri Apr 24 21:04:19 2026 +0200 Gitea Actions Podman build and push diff --git a/README.md b/README.md new file mode 100644 index 0000000..6764e97 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# Gitea Actions + +Reusable Gitea Actions composite workflows for noctrl infrastructure automation. + +## Available Actions + +### Podman Build And Publish + +Builds and optionally pushes OCI container images to `registry.noctrl.eu` using Podman with isolated storage context. + +**Location:** [`./podman-build-publish`](./podman-build-publish) + +**Use in workflows:** +```yaml +- uses: https://gitea.noctrl.eu/noctrl/actions/podman-build-publish@v1 + with: + image-name: noctrl/myapp + tags: | + latest + sha-${{ github.sha }} +``` + +See [podman-build-publish README](./podman-build-publish/README.md) for full documentation. + +## Usage + +Reference actions by absolute URL in your workflow: + +```yaml +- uses: https://gitea.noctrl.eu/noctrl/actions/@ +``` + +**Ref Options:** +- `@v1` — points to tag `v1` +- `@main` — points to default branch +- `@commit-sha` — points to specific commit + +## Repository Secrets + +Actions reference caller repository secrets. Ensure your repository has required secrets defined: + +- **REGISTRY_USERNAME** — registry.noctrl.eu authentication username +- **REGISTRY_PASSWORD** — registry.noctrl.eu authentication password + +Set these in repository **Settings** → **Secrets**. + +## Contributing + +When adding new actions: +1. Create action directory: `./action-name/` +2. Include `action.yaml` (composite action definition) +3. Include `README.md` with inputs, outputs, and usage example +4. Tag stable versions: `git tag v1`, `git tag v2`, etc. +5. Update this root README diff --git a/podman-build-publish/README.md b/podman-build-publish/README.md new file mode 100644 index 0000000..3b8cf6d --- /dev/null +++ b/podman-build-publish/README.md @@ -0,0 +1,51 @@ +# Podman Build And Publish Action + +Composite action that builds and optionally pushes OCI images with Podman to `registry.noctrl.eu`. + +## Inputs + +- `image-name` (required): repository path, for example `noctrl/gitea-runner` +- `tags` (required): newline, comma, or space separated tags +- `context` (optional, default `.`): build context +- `containerfile` (optional, default `Containerfile`): containerfile path +- `build-args` (optional): newline-separated `KEY=VALUE` +- `push` (optional, default `true`): whether to push image tags + +## Required Secrets + +The following repository secrets must be defined to push images: +- `REGISTRY_USERNAME`: registry authentication username +- `REGISTRY_PASSWORD`: registry authentication password + +The action uses fixed Podman defaults matching the runner workflows: +- root: `${RUNNER_TEMP}/podman-root` +- runroot: `${RUNNER_TEMP}/podman-runroot` +- storage driver: `vfs` +- build isolation: `chroot` +- registry: `registry.noctrl.eu` (hardcoded) + +## Example + +```yaml +jobs: + build-and-push: + runs-on: [linux, build] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build and push image + uses: https://gitea.noctrl.eu/noctrl/actions/podman-build-publish@v1 + with: + image-name: noctrl/gitea-runner + tags: | + latest + sha-${{ github.sha }} + context: . + containerfile: Containerfile + build-args: | + ACT_RUNNER_VERSION=0.2.11 + push: "true" +``` + +> **Note:** The action accesses `${{ secrets.REGISTRY_USERNAME }}` and `${{ secrets.REGISTRY_PASSWORD }}` from the calling repository's secrets context. These must be defined in the caller's repository settings. diff --git a/podman-build-publish/action.yaml b/podman-build-publish/action.yaml new file mode 100644 index 0000000..0f8bc8f --- /dev/null +++ b/podman-build-publish/action.yaml @@ -0,0 +1,137 @@ +name: Podman Build And Publish +description: Build and optionally push OCI images with Podman to registry.noctrl.eu. + +inputs: + image-name: + description: Repository/image name path, for example noctrl/gitea-runner + required: true + tags: + description: | + Tags to apply and push. Supports newline, comma, or space separated values. + Example: "latest\nsha-abc123" + required: true + context: + description: Build context path. + required: false + default: . + containerfile: + description: Containerfile or Dockerfile path. + required: false + default: Containerfile + build-args: + description: | + Optional build args as newline-separated KEY=VALUE entries. + Example: "ACT_RUNNER_VERSION=0.2.11" + required: false + default: "" + push: + description: Push image tags after build. + required: false + default: "true" + +runs: + using: composite + steps: + - id: initialize + shell: bash + run: | + set -euo pipefail + + # Keep Podman defaults aligned with runner build workflows. + podman_root="${RUNNER_TEMP}/podman-root" + podman_runroot="${RUNNER_TEMP}/podman-runroot" + storage_driver="vfs" + build_isolation="chroot" + + rm -rf "${podman_root}" "${podman_runroot}" + mkdir -p "${podman_root}" "${podman_runroot}" + + # Export for use in subsequent steps + { + echo "PODMAN_ROOT=${podman_root}" + echo "PODMAN_RUNROOT=${podman_runroot}" + echo "STORAGE_DRIVER=${storage_driver}" + echo "BUILD_ISOLATION=${build_isolation}" + echo "IMAGE_BASE=registry.noctrl.eu/${{ inputs.image-name }}" + } >> "${GITHUB_ENV}" + + # Parse and validate tags + mapfile -t tags < <(printf '%s\n' "${{ inputs.tags }}" | tr ', ' '\n\n' | sed '/^$/d') + if [[ ${#tags[@]} -eq 0 ]]; then + echo "ERROR: no tags resolved from inputs.tags" >&2 + exit 1 + fi + + # Export tags as newline-separated string for subsequent steps + (IFS=$'\n'; echo "IMAGE_TAGS=${tags[*]}") >> "${GITHUB_ENV}" + + - id: login + shell: bash + run: | + set -euo pipefail + + if [[ -n "${{ secrets.REGISTRY_USERNAME }}" && -n "${{ secrets.REGISTRY_PASSWORD }}" ]]; then + podman_args=( + --root "${PODMAN_ROOT}" + --runroot "${PODMAN_RUNROOT}" + --storage-driver "${STORAGE_DRIVER}" + ) + + echo "Logging in to registry: registry.noctrl.eu" + echo "${{ secrets.REGISTRY_PASSWORD }}" | podman "${podman_args[@]}" login registry.noctrl.eu -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin + else + echo "Registry credentials not available (REGISTRY_USERNAME and REGISTRY_PASSWORD secrets required for push)" + fi + + - id: build + shell: bash + run: | + set -euo pipefail + + podman_args=( + --root "${PODMAN_ROOT}" + --runroot "${PODMAN_RUNROOT}" + --storage-driver "${STORAGE_DRIVER}" + ) + + build_cmd=(podman "${podman_args[@]}" build --isolation "${BUILD_ISOLATION}" -f "${{ inputs.containerfile }}") + + # Add build args + while IFS= read -r build_arg; do + [[ -z "${build_arg}" ]] && continue + build_cmd+=(--build-arg "${build_arg}") + done <<< "${{ inputs.build-args }}" + + # Add tags + echo "Building image with tags:" + while IFS= read -r tag; do + [[ -z "${tag}" ]] && continue + echo " ${IMAGE_BASE}:${tag}" + build_cmd+=(-t "${IMAGE_BASE}:${tag}") + done <<< "${IMAGE_TAGS}" + + build_cmd+=("${{ inputs.context }}") + "${build_cmd[@]}" + + - id: push + shell: bash + run: | + set -euo pipefail + + if [[ "${{ inputs.push }}" != "true" ]]; then + echo "Push disabled by input push=${{ inputs.push }}" + exit 0 + fi + + podman_args=( + --root "${PODMAN_ROOT}" + --runroot "${PODMAN_RUNROOT}" + --storage-driver "${STORAGE_DRIVER}" + ) + + echo "Pushing image tags:" + while IFS= read -r tag; do + [[ -z "${tag}" ]] && continue + echo " ${IMAGE_BASE}:${tag}" + podman "${podman_args[@]}" push "${IMAGE_BASE}:${tag}" + done <<< "${IMAGE_TAGS}"