feat: complete Gitea Actions CI workflow for container builds
Some checks failed
Build containers when image tags change / build-if-image-changed (., shorefront-backend, shorefront backend, backend/Dockerfile, git.baumann.gr/adebaumann/shorefront-backend, .backend.image) (push) Failing after 41s
Build containers when image tags change / build-if-image-changed (., shorefront-frontend, shorefront frontend, frontend/Dockerfile, git.baumann.gr/adebaumann/shorefront-frontend, .frontend.image) (push) Failing after 41s
Some checks failed
Build containers when image tags change / build-if-image-changed (., shorefront-backend, shorefront backend, backend/Dockerfile, git.baumann.gr/adebaumann/shorefront-backend, .backend.image) (push) Failing after 41s
Build containers when image tags change / build-if-image-changed (., shorefront-frontend, shorefront frontend, frontend/Dockerfile, git.baumann.gr/adebaumann/shorefront-frontend, .frontend.image) (push) Failing after 41s
- Fix trigger/env path: Helm/ -> helm/ (was wrong case) - Add image_yq_path and dockerfile to matrix so each container uses its own values.yaml key and Dockerfile path - Fix yq paths: .django.image.* -> .frontend.image/.backend.image for repo, .containers.version for tag (single source of truth) - Add file: param to docker/build-push-action (Dockerfiles are in frontend/ and backend/, not repo root) - values.yaml: add registry prefix to image fields so k8s pulls from git.baumann.gr; quote containers.version; drop per-component tag fields (containers.version is now the single tag source) - Deployment templates: use .containers.version for image tag Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
171
.gitea/workflows/build-containers-on-demand.yml
Normal file
171
.gitea/workflows/build-containers-on-demand.yml
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
name: Build containers when image tags change
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
# Uncomment/adjust once working:
|
||||||
|
# branches: [ master ]
|
||||||
|
paths:
|
||||||
|
- "helm/shorefront/values.yaml"
|
||||||
|
- "frontend/Dockerfile"
|
||||||
|
- "backend/Dockerfile"
|
||||||
|
- ".gitea/workflows/build-containers-on-demand.yml"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-if-image-changed:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- container_name: shorefront-frontend
|
||||||
|
image_yq_path: .frontend.image
|
||||||
|
expected_repo: git.baumann.gr/adebaumann/shorefront-frontend
|
||||||
|
dockerfile: frontend/Dockerfile
|
||||||
|
build_context: .
|
||||||
|
description: shorefront frontend
|
||||||
|
- container_name: shorefront-backend
|
||||||
|
image_yq_path: .backend.image
|
||||||
|
expected_repo: git.baumann.gr/adebaumann/shorefront-backend
|
||||||
|
dockerfile: backend/Dockerfile
|
||||||
|
build_context: .
|
||||||
|
description: shorefront backend
|
||||||
|
|
||||||
|
env:
|
||||||
|
DEPLOY_FILE: "helm/shorefront/values.yaml"
|
||||||
|
CONTAINER_NAME: ${{ matrix.container_name }}
|
||||||
|
EXPECTED_REPO: ${{ matrix.expected_repo }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
|
||||||
|
- name: Determine base commit
|
||||||
|
id: base
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if git rev-parse --verify -q HEAD~1 >/dev/null; then
|
||||||
|
echo "base=$(git rev-parse HEAD~1)" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "base=$(git hash-object -t tree /dev/null)" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install yq
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
YQ_VER=v4.44.3
|
||||||
|
curl -sL "https://github.com/mikefarah/yq/releases/download/${YQ_VER}/yq_linux_amd64" -o /usr/local/bin/yq
|
||||||
|
chmod +x /usr/local/bin/yq
|
||||||
|
yq --version
|
||||||
|
|
||||||
|
- name: Read ${{ matrix.description }} image from Helm values
|
||||||
|
id: img
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
file="${DEPLOY_FILE}"
|
||||||
|
expected_repo="${EXPECTED_REPO}"
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo "Reading image from: $file"
|
||||||
|
echo "Expected repo: $expected_repo"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
new_repo=$(yq -r '${{ matrix.image_yq_path }}' "$file")
|
||||||
|
new_tag=$(yq -r '.containers.version' "$file")
|
||||||
|
new_image="${new_repo}:${new_tag}"
|
||||||
|
|
||||||
|
if git cat-file -e "${{ steps.base.outputs.base }}:$file" 2>/dev/null; then
|
||||||
|
old_repo=$(git show "${{ steps.base.outputs.base }}:$file" | yq -r '${{ matrix.image_yq_path }}' || true)
|
||||||
|
old_tag=$(git show "${{ steps.base.outputs.base }}:$file" | yq -r '.containers.version' || true)
|
||||||
|
old_image="${old_repo}:${old_tag}"
|
||||||
|
else
|
||||||
|
old_image="<none>"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Old image: ${old_image}"
|
||||||
|
echo "New image: ${new_image}"
|
||||||
|
|
||||||
|
if [ -z "${new_repo:-}" ] || [ "$new_repo" = "null" ]; then
|
||||||
|
echo "ERROR: Could not read ${{ matrix.image_yq_path }} from $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$new_repo" != "$expected_repo" ]]; then
|
||||||
|
echo "ERROR: Found image repo \"$new_repo\" but expected \"$expected_repo\""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
registry="$(echo "$new_repo" | awk -F/ '{print $1}')"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "new_image=$new_image"
|
||||||
|
echo "new_repo=$new_repo"
|
||||||
|
echo "new_tag=$new_tag"
|
||||||
|
echo "registry=$registry"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Check if image exists on registry
|
||||||
|
id: check_image
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
new_repo="${{ steps.img.outputs.new_repo }}"
|
||||||
|
new_tag="${{ steps.img.outputs.new_tag }}"
|
||||||
|
registry_user="${{ gitea.actor }}"
|
||||||
|
registry_password="${{ secrets.REGISTRY_TOKEN }}"
|
||||||
|
|
||||||
|
registry_host=$(echo "$new_repo" | cut -d/ -f1)
|
||||||
|
image_path=$(echo "$new_repo" | cut -d/ -f2-)
|
||||||
|
|
||||||
|
echo "Checking if $new_repo:$new_tag exists on registry $registry_host"
|
||||||
|
|
||||||
|
manifest_url="https://${registry_host}/v2/${image_path}/manifests/${new_tag}"
|
||||||
|
|
||||||
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
|
-u "${registry_user}:${registry_password}" \
|
||||||
|
-H "Accept: application/vnd.docker.distribution.manifest.v2+json,application/vnd.docker.distribution.manifest.list.v2+json" \
|
||||||
|
"$manifest_url" || echo "000")
|
||||||
|
|
||||||
|
if [ "$http_code" = "200" ]; then
|
||||||
|
echo "Image already exists on registry (HTTP $http_code)"
|
||||||
|
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "Image does not exist on registry (HTTP $http_code)"
|
||||||
|
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Skip if image already exists
|
||||||
|
if: steps.check_image.outputs.exists == 'true'
|
||||||
|
run: echo "${{ matrix.description }} image ${{ steps.img.outputs.new_image }} already exists on registry; skipping build."
|
||||||
|
|
||||||
|
- name: Set up Buildx
|
||||||
|
if: steps.check_image.outputs.exists == 'false'
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to registry
|
||||||
|
if: steps.check_image.outputs.exists == 'false'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ steps.img.outputs.registry }}
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push ${{ matrix.description }} (exact tag from Helm values)
|
||||||
|
if: steps.check_image.outputs.exists == 'false'
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: ${{ matrix.build_context }}
|
||||||
|
file: ${{ matrix.dockerfile }}
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ steps.img.outputs.new_image }}
|
||||||
|
${{ steps.img.outputs.new_repo }}:latest
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.source=${{ gitea.repository }}
|
||||||
|
org.opencontainers.image.revision=${{ gitea.sha }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
@@ -18,7 +18,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: migrate
|
- name: migrate
|
||||||
image: "{{ .Values.backend.image }}:{{ .Values.backend.tag }}"
|
image: "{{ .Values.backend.image }}:{{ .Values.containers.version }}"
|
||||||
command: ["alembic", "upgrade", "head"]
|
command: ["alembic", "upgrade", "head"]
|
||||||
env:
|
env:
|
||||||
- name: POSTGRES_PASSWORD
|
- name: POSTGRES_PASSWORD
|
||||||
@@ -30,7 +30,7 @@ spec:
|
|||||||
value: "postgresql://{{ .Values.postgres.user }}:$(POSTGRES_PASSWORD)@postgres:5432/{{ .Values.postgres.database }}"
|
value: "postgresql://{{ .Values.postgres.user }}:$(POSTGRES_PASSWORD)@postgres:5432/{{ .Values.postgres.database }}"
|
||||||
containers:
|
containers:
|
||||||
- name: backend
|
- name: backend
|
||||||
image: "{{ .Values.backend.image }}:{{ .Values.backend.tag }}"
|
image: "{{ .Values.backend.image }}:{{ .Values.containers.version }}"
|
||||||
command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
env:
|
env:
|
||||||
- name: POSTGRES_PASSWORD
|
- name: POSTGRES_PASSWORD
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ spec:
|
|||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: frontend
|
- name: frontend
|
||||||
image: "{{ .Values.frontend.image }}:{{ .Values.frontend.tag }}"
|
image: "{{ .Values.frontend.image }}:{{ .Values.containers.version }}"
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
resources:
|
resources:
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
namespace: shorefront
|
namespace: shorefront
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
image: shorefront-backend
|
image: git.baumann.gr/adebaumann/shorefront-backend
|
||||||
tag: latest
|
|
||||||
replicas: 1
|
replicas: 1
|
||||||
resources:
|
resources:
|
||||||
requests: { cpu: 100m, memory: 128Mi }
|
requests: { cpu: 100m, memory: 128Mi }
|
||||||
limits: { cpu: 500m, memory: 512Mi }
|
limits: { cpu: 500m, memory: 512Mi }
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: shorefront-frontend
|
image: git.baumann.gr/adebaumann/shorefront-frontend
|
||||||
tag: latest
|
|
||||||
replicas: 1
|
replicas: 1
|
||||||
resources:
|
resources:
|
||||||
requests: { cpu: 50m, memory: 64Mi }
|
requests: { cpu: 50m, memory: 64Mi }
|
||||||
@@ -33,3 +31,6 @@ nfs:
|
|||||||
ingress:
|
ingress:
|
||||||
host: shorefront.example.com
|
host: shorefront.example.com
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
|
|
||||||
|
containers:
|
||||||
|
version: "0.001"
|
||||||
|
|||||||
Reference in New Issue
Block a user