Die bisher in einem einzelnen Projekt liegende Pipeline zieht als wiederverwendbarer Workflow (on: workflow_call) nach .gitea/workflows/docker-build-push.yml um. Inhaltlich geaendert ist genau eine Stelle: Der Eigentuemer des Images stand als IMAGE_OWNER fest im env-Block des Workflows, wodurch jedes Image jedes aufrufenden Projekts unter git.jk-dev.de/suer/... gelandet waere. Er ist jetzt die Eingabe image-owner mit suer als Vorgabewert, sodass bestehende Aufrufer unveraendert weiterlaufen. Der Wert kann nicht im env-Block bleiben: env auf Workflow-Ebene wird ausgewertet, bevor es einen inputs-Kontext gibt. Die Tag-Liste liest ihn deshalb unmittelbar aus inputs. Alles Uebrige ist unveraendert uebernommen, samt der Kommentare, die das Warum erklaeren: 1Password Connect, runs-on, DOCKER_HOST, Diagnoseschritt, Multi-Arch und Tag-Schema. Die README dokumentiert Eingaben, ein vollstaendiges Aufrufbeispiel, die Voraussetzungen im aufrufenden Repository und den Hinweis, auf einen Tag statt auf @main zu zeigen.
147 lines
6.3 KiB
YAML
147 lines
6.3 KiB
YAML
on:
|
|
workflow_call:
|
|
inputs:
|
|
version-number:
|
|
required: true
|
|
type: string
|
|
version-number-major:
|
|
required: true
|
|
type: string
|
|
version-number-minor:
|
|
required: true
|
|
type: string
|
|
version-number-patch:
|
|
required: true
|
|
type: string
|
|
container-name:
|
|
required: true
|
|
type: string
|
|
dockerfile:
|
|
required: true
|
|
type: string
|
|
docker-context:
|
|
required: true
|
|
type: string
|
|
image-owner:
|
|
description: >-
|
|
Owner segment of the pushed image, i.e. the middle part of
|
|
<registry>/<owner>/<container-name>. Used to be hardcoded to "suer",
|
|
which sent every image of every calling project to the same account.
|
|
Kept as the default so existing callers stay unchanged.
|
|
required: false
|
|
default: suer
|
|
type: string
|
|
timeout-minutes:
|
|
description: 'Hard limit for the build job. Without one a wedged build runs into the 6h default.'
|
|
required: false
|
|
default: 45
|
|
type: number
|
|
platforms:
|
|
description: >-
|
|
Target platforms of the pushed manifest list. The build stages of all
|
|
dockerfiles are pinned to the build platform, so an extra platform only
|
|
adds its runtime stage, not another compile run.
|
|
required: false
|
|
default: linux/amd64,linux/arm64
|
|
type: string
|
|
build-args:
|
|
description: >-
|
|
Extra build arguments for the image, one NAME=value per line. The docs
|
|
image uses it to stamp the released version into writerside.cfg.
|
|
required: false
|
|
default: ''
|
|
type: string
|
|
|
|
name: build and push Docker Image
|
|
|
|
env:
|
|
REGISTRY: git.jk-dev.de
|
|
|
|
jobs:
|
|
build-image:
|
|
name: Build ${{ inputs.container-name }} Container
|
|
permissions:
|
|
packages: write
|
|
contents: read
|
|
runs-on: [ ubuntu-docker ]
|
|
timeout-minutes: ${{ inputs.timeout-minutes }}
|
|
env:
|
|
# Ohne Angabe suchen Buildx und die Docker-CLI unter
|
|
# unix:///var/run/docker.sock. Laeuft der Daemon des Runners rootless,
|
|
# liegt sein Socket stattdessen unter /run/user/<uid>/docker.sock. Der
|
|
# Pfad kommt deshalb aus einer Repository-Variablen; ist sie nicht
|
|
# gesetzt, bleibt die Variable leer und Docker nutzt seinen Default.
|
|
DOCKER_HOST: ${{ vars.DOCKER_HOST }}
|
|
steps:
|
|
# Der Token, den Gitea jedem Job stellt, taugt fuer zwei Dinge nicht:
|
|
# Er gilt nur fuer das ausfuehrende Repository, waehrend die Submodule in
|
|
# eigenen, privaten Repositories liegen — deren Klon scheitert an
|
|
# "Repository not found". Und die Container-Registry lehnt ihn ab
|
|
# (container.Authenticate antwortet mit 401). Beides deckt je ein eigener
|
|
# Zugang ab, gepflegt in 1Password und hier zur Laufzeit ueber den
|
|
# Connect-Server im Cluster geholt; in Gitea liegt nur dessen Zugang.
|
|
- name: Zugangsdaten aus 1Password laden
|
|
id: op-secrets
|
|
uses: 1password/load-secrets-action@v2
|
|
with:
|
|
# Die Werte sollen nur als Step-Outputs entstehen und nicht in die
|
|
# Umgebung aller folgenden Schritte wandern.
|
|
export-env: false
|
|
env:
|
|
OP_CONNECT_HOST: ${{ vars.OP_CONNECT_HOST }}
|
|
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
|
|
# Klont die privaten Submodul-Repositories.
|
|
CHECKOUT_TOKEN: op://GitHub-Actions/jlab-git-checkout-token/credential
|
|
# Eigener Zugang fuer die Registry — der Checkout-Token darf dort
|
|
# nicht schreiben. Benutzername und Token kommen aus demselben Item,
|
|
# damit sie zwangslaeufig zusammenpassen; die Registry prueft den
|
|
# Token gegen genau das Konto aus `username`.
|
|
REGISTRY_USER: op://GitHub-Actions/jlab-registry-access/username
|
|
REGISTRY_TOKEN: op://GitHub-Actions/jlab-registry-access/password
|
|
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
submodules: true
|
|
# Die Action legt je Referenz einen Output an, benannt wie die
|
|
# Umgebungsvariable, in der die op://-Referenz stand.
|
|
token: ${{ steps.op-secrets.outputs.CHECKOUT_TOKEN }}
|
|
# Schlaegt der Buildx-Start fehl, ist die erste Frage immer, welcher
|
|
# Socket im Job-Container ueberhaupt ankommt. Der Schritt beantwortet sie,
|
|
# ohne den Job scheitern zu lassen.
|
|
- name: Docker-Socket ermitteln
|
|
run: |
|
|
echo "DOCKER_HOST=${DOCKER_HOST:-<leer, Default wird genutzt>}"
|
|
ls -l /var/run/docker.sock /run/docker.sock 2>&1 || true
|
|
ls -l /run/user/*/docker.sock 2>&1 || true
|
|
docker version 2>&1 || true
|
|
|
|
- name: Set up Docker Buildx
|
|
id: buildx
|
|
uses: docker/setup-buildx-action@master
|
|
- name: Authenticate To Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ steps.op-secrets.outputs.REGISTRY_USER }}
|
|
password: ${{ steps.op-secrets.outputs.REGISTRY_TOKEN }}
|
|
- name: Build
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
builder: ${{ steps.buildx.outputs.name }}
|
|
context: ${{ inputs.docker-context }}
|
|
file: ${{ inputs.dockerfile }}
|
|
platforms: ${{ inputs.platforms }}
|
|
build-args: ${{ inputs.build-args }}
|
|
push: true
|
|
# Der Eigentümer stand frueher als IMAGE_OWNER im env-Block des
|
|
# Workflows. Dort kann er nicht bleiben: env auf Workflow-Ebene wird
|
|
# ausgewertet, bevor es einen inputs-Kontext gibt. Der Wert wird
|
|
# deshalb hier unmittelbar aus inputs gelesen — an dieser Stelle ist
|
|
# der Kontext sicher vorhanden, anders als in jedem env-Block.
|
|
tags: |
|
|
${{ env.REGISTRY }}/${{ inputs.image-owner }}/${{ inputs.container-name }}:latest
|
|
${{ env.REGISTRY }}/${{ inputs.image-owner }}/${{ inputs.container-name }}:${{ inputs.version-number }}
|
|
${{ env.REGISTRY }}/${{ inputs.image-owner }}/${{ inputs.container-name }}:${{ inputs.version-number-major }}
|
|
${{ env.REGISTRY }}/${{ inputs.image-owner }}/${{ inputs.container-name }}:${{ inputs.version-number-major }}.${{ inputs.version-number-minor }}
|
|
${{ env.REGISTRY }}/${{ inputs.image-owner }}/${{ inputs.container-name }}:${{ inputs.version-number-major }}.${{ inputs.version-number-minor }}.${{ inputs.version-number-patch }}
|