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:
|
||||
initContainers:
|
||||
- name: migrate
|
||||
image: "{{ .Values.backend.image }}:{{ .Values.backend.tag }}"
|
||||
image: "{{ .Values.backend.image }}:{{ .Values.containers.version }}"
|
||||
command: ["alembic", "upgrade", "head"]
|
||||
env:
|
||||
- name: POSTGRES_PASSWORD
|
||||
@@ -30,7 +30,7 @@ spec:
|
||||
value: "postgresql://{{ .Values.postgres.user }}:$(POSTGRES_PASSWORD)@postgres:5432/{{ .Values.postgres.database }}"
|
||||
containers:
|
||||
- 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"]
|
||||
env:
|
||||
- name: POSTGRES_PASSWORD
|
||||
|
||||
@@ -18,7 +18,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: frontend
|
||||
image: "{{ .Values.frontend.image }}:{{ .Values.frontend.tag }}"
|
||||
image: "{{ .Values.frontend.image }}:{{ .Values.containers.version }}"
|
||||
ports:
|
||||
- containerPort: 80
|
||||
resources:
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
namespace: shorefront
|
||||
|
||||
backend:
|
||||
image: shorefront-backend
|
||||
tag: latest
|
||||
image: git.baumann.gr/adebaumann/shorefront-backend
|
||||
replicas: 1
|
||||
resources:
|
||||
requests: { cpu: 100m, memory: 128Mi }
|
||||
limits: { cpu: 500m, memory: 512Mi }
|
||||
|
||||
frontend:
|
||||
image: shorefront-frontend
|
||||
tag: latest
|
||||
image: git.baumann.gr/adebaumann/shorefront-frontend
|
||||
replicas: 1
|
||||
resources:
|
||||
requests: { cpu: 50m, memory: 64Mi }
|
||||
@@ -33,3 +31,6 @@ nfs:
|
||||
ingress:
|
||||
host: shorefront.example.com
|
||||
ingressClassName: traefik
|
||||
|
||||
containers:
|
||||
version: "0.001"
|
||||
|
||||
Reference in New Issue
Block a user