Geteilte Docker-Build-and-Push-Pipeline anlegen
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.
This commit is contained in:
2 files changed
+238
-1
No files matched your search
@@ -0,0 +1,146 @@
|
||||
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 }}
|
||||
Reference in new issue
Block a user