Skip to content

Merge pull request #686 from netzbegruenung/chore/deps-update-2026-04-26 #953

Merge pull request #686 from netzbegruenung/chore/deps-update-2026-04-26

Merge pull request #686 from netzbegruenung/chore/deps-update-2026-04-26 #953

Workflow file for this run

name: Build and Push Docker Images
on:
push:
branches:
- master
- test-branch
paths:
- 'apps/**'
- 'services/**'
- 'packages/**'
- 'documentation/**'
- 'pnpm-lock.yaml'
- 'nginx.conf'
- 'docker-compose.prod.yml'
- '.github/workflows/build-images.yml'
workflow_dispatch:
inputs:
force_all:
description: 'Build all images regardless of changes'
required: false
default: 'false'
type: boolean
build_web:
description: 'Build web image only'
required: false
default: 'false'
type: boolean
build_api:
description: 'Build API image only'
required: false
default: 'false'
type: boolean
build_docs:
description: 'Build docs image only'
required: false
default: 'false'
type: boolean
build_mcp:
description: 'Build MCP image only'
required: false
default: 'false'
type: boolean
build_doku:
description: 'Build doku image only'
required: false
default: 'false'
type: boolean
build_sites:
description: 'Build sites image only'
required: false
default: 'false'
type: boolean
build_hocuspocus:
description: 'Build hocuspocus image only'
required: false
default: 'false'
type: boolean
build_gruen_o_mat:
description: 'Build gruen-o-mat image only'
required: false
default: 'false'
type: boolean
build_voxtral:
description: 'Build voxtral image only'
required: false
default: 'false'
type: boolean
build_nlp:
description: 'Build NLP image only'
required: false
default: 'false'
type: boolean
build_iconify:
description: 'Build Iconify image only'
required: false
default: 'false'
type: boolean
permissions:
contents: read
packages: write
# Serialize builds per branch so concurrent merges can't race for the `:latest` tag.
# `cancel-in-progress: false` queues runs — each commit still gets its immutable
# `:sha-XXXXXXX` tag, and `:latest` always reflects merge order.
concurrency:
group: build-images-${{ github.ref }}
cancel-in-progress: false
env:
REGISTRY: ghcr.io
IMAGE_PREFIX: ghcr.io/${{ github.repository_owner }}/gruenerator
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
web: ${{ steps.filter.outputs.web }}
api: ${{ steps.filter.outputs.api }}
sites: ${{ steps.filter.outputs.sites }}
docs: ${{ steps.filter.outputs.docs }}
hocuspocus: ${{ steps.filter.outputs.hocuspocus }}
mcp: ${{ steps.filter.outputs.mcp }}
doku: ${{ steps.filter.outputs.doku }}
gruen-o-mat: ${{ steps.filter.outputs.gruen-o-mat }}
voxtral: ${{ steps.filter.outputs.voxtral }}
nlp: ${{ steps.filter.outputs.nlp }}
iconify: ${{ steps.filter.outputs.iconify }}
shared: ${{ steps.filter.outputs.shared }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- uses: dorny/paths-filter@v3
id: filter
with:
base: ${{ github.event.before }}
filters: |
shared:
- 'packages/shared/**'
- 'pnpm-lock.yaml'
web:
- 'apps/web/**'
- 'packages/shared/**'
- 'packages/docs/**'
- 'packages/chat/**'
- 'packages/voice/**'
- 'packages/canvas-editor/**'
- 'packages/ui/**'
- 'packages/collab/**'
- 'packages/wolke/**'
- 'pnpm-lock.yaml'
api:
- 'apps/api/**'
- 'packages/shared/**'
- 'pnpm-lock.yaml'
sites:
- 'apps/sites/**'
- 'packages/shared/**'
- 'packages/sites-design/**'
- 'pnpm-lock.yaml'
docs:
- 'apps/docs/**'
- 'packages/shared/**'
- 'packages/docs/**'
- 'packages/collab/**'
- 'packages/ui/**'
- 'packages/wolke/**'
- 'pnpm-lock.yaml'
hocuspocus:
- 'services/hocuspocus/**'
- 'packages/shared/**'
- 'pnpm-lock.yaml'
mcp:
- 'services/mcp/**'
- 'packages/shared/**'
- 'pnpm-lock.yaml'
gruen-o-mat:
- 'apps/gruen-o-mat/**'
- 'packages/chat/**'
- 'packages/voice/**'
- 'packages/shared/**'
- 'packages/ui/**'
- 'packages/collab/**'
- 'pnpm-lock.yaml'
voxtral:
- 'services/voxtral/**'
nlp:
- 'services/nlp/**'
iconify:
- 'services/iconify/**'
doku:
- 'documentation/**'
build-web:
needs: detect-changes
if: >
needs.detect-changes.outputs.web == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_web == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-web
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: apps/web/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-web:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-web:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-args: |
VITE_API_BASE_URL=/api
VITE_APP_ENV=production
VITE_SENTRY_DSN=${{ vars.VITE_SENTRY_DSN }}
build-api:
needs: detect-changes
if: >
needs.detect-changes.outputs.api == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_api == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-api
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: apps/api/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-api:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-api:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-sites:
needs: detect-changes
if: >
needs.detect-changes.outputs.sites == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_sites == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-sites
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: apps/sites/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-sites:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-sites:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-args: |
VITE_API_BASE_URL=/api
VITE_APP_ENV=production
VITE_SENTRY_DSN=${{ vars.VITE_SENTRY_DSN }}
build-docs:
needs: detect-changes
if: >
needs.detect-changes.outputs.docs == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_docs == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-docs
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: apps/docs/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-docs:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-docs:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-hocuspocus:
needs: detect-changes
if: >
needs.detect-changes.outputs.hocuspocus == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_hocuspocus == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-hocuspocus
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: services/hocuspocus/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-hocuspocus:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-hocuspocus:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-mcp:
needs: detect-changes
if: >
needs.detect-changes.outputs.mcp == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_mcp == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-mcp
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: services/mcp/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-mcp:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-mcp:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-gruen-o-mat:
needs: detect-changes
if: >
needs.detect-changes.outputs.gruen-o-mat == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_gruen_o_mat == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-gruen-o-mat
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: apps/gruen-o-mat/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-gruen-o-mat:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-gruen-o-mat:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-voxtral:
needs: detect-changes
if: >
needs.detect-changes.outputs.voxtral == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_voxtral == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-voxtral
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./services/voxtral
file: services/voxtral/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-voxtral:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-voxtral:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-nlp:
needs: detect-changes
if: >
needs.detect-changes.outputs.nlp == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_nlp == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-nlp
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./services/nlp
file: services/nlp/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-nlp:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-nlp:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-iconify:
needs: detect-changes
if: >
needs.detect-changes.outputs.iconify == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_iconify == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-iconify
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./services/iconify
file: services/iconify/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-iconify:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-iconify:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
build-doku:
needs: detect-changes
if: >
needs.detect-changes.outputs.doku == 'true' ||
github.event.inputs.force_all == 'true' ||
github.event.inputs.build_doku == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_PREFIX }}-doku
tags: |
type=ref,event=branch
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./documentation
file: documentation/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ env.IMAGE_PREFIX }}-doku:buildcache
cache-to: type=registry,ref=${{ env.IMAGE_PREFIX }}-doku:buildcache,mode=max,image-manifest=true,oci-mediatypes=true
summary:
needs:
[
build-web,
build-api,
build-sites,
build-docs,
build-hocuspocus,
build-mcp,
build-gruen-o-mat,
build-voxtral,
build-nlp,
build-iconify,
build-doku,
]
if: always()
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Build Summary
run: |
echo "## Build Results" >> $GITHUB_STEP_SUMMARY
echo "| Service | Status |" >> $GITHUB_STEP_SUMMARY
echo "|---------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| web | ${{ needs.build-web.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| api | ${{ needs.build-api.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| sites | ${{ needs.build-sites.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| docs | ${{ needs.build-docs.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| hocuspocus | ${{ needs.build-hocuspocus.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| mcp | ${{ needs.build-mcp.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| gruen-o-mat | ${{ needs.build-gruen-o-mat.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| voxtral | ${{ needs.build-voxtral.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| nlp | ${{ needs.build-nlp.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| iconify | ${{ needs.build-iconify.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| doku | ${{ needs.build-doku.result }} |" >> $GITHUB_STEP_SUMMARY