00d7c6c2f3
Add a preflight change-detection job to the Docker publish workflow and derive the build matrix from shared-root and service-specific path filters. Preserve full publishes on manual dispatch while skipping unaffected service image builds on routine pushes.
136 lines
4.5 KiB
YAML
136 lines
4.5 KiB
YAML
name: Docker Publish
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
|
|
jobs:
|
|
detect-changes:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
shared: ${{ steps.manual.outputs.shared || steps.filter.outputs.shared }}
|
|
frontend: ${{ steps.manual.outputs.frontend || steps.filter.outputs.frontend }}
|
|
backend: ${{ steps.manual.outputs.backend || steps.filter.outputs.backend }}
|
|
remote_gateway: ${{ steps.manual.outputs.remote_gateway || steps.filter.outputs.remote_gateway }}
|
|
matrix: ${{ steps.matrix.outputs.matrix }}
|
|
has_changes: ${{ steps.matrix.outputs.has_changes }}
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
if: github.event_name != 'workflow_dispatch'
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Mark all services changed for manual dispatch
|
|
if: github.event_name == 'workflow_dispatch'
|
|
id: manual
|
|
run: |
|
|
echo "shared=true" >> "$GITHUB_OUTPUT"
|
|
echo "frontend=true" >> "$GITHUB_OUTPUT"
|
|
echo "backend=true" >> "$GITHUB_OUTPUT"
|
|
echo "remote_gateway=true" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Detect changed paths
|
|
if: github.event_name != 'workflow_dispatch'
|
|
id: filter
|
|
uses: dorny/paths-filter@v3
|
|
with:
|
|
filters: |
|
|
shared:
|
|
- '.github/workflows/docker-publish.yml'
|
|
- 'package.json'
|
|
- 'package-lock.json'
|
|
- 'docker-compose.yml'
|
|
- 'patches/**'
|
|
frontend:
|
|
- 'packages/frontend/**'
|
|
backend:
|
|
- 'packages/backend/**'
|
|
remote_gateway:
|
|
- 'packages/remote-gateway/**'
|
|
|
|
- name: Build service matrix
|
|
id: matrix
|
|
env:
|
|
SHARED: ${{ steps.manual.outputs.shared || steps.filter.outputs.shared }}
|
|
FRONTEND: ${{ steps.manual.outputs.frontend || steps.filter.outputs.frontend }}
|
|
BACKEND: ${{ steps.manual.outputs.backend || steps.filter.outputs.backend }}
|
|
REMOTE_GATEWAY: ${{ steps.manual.outputs.remote_gateway || steps.filter.outputs.remote_gateway }}
|
|
run: |
|
|
python <<'PY'
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
shared = os.environ.get("SHARED") == "true"
|
|
services = [
|
|
("frontend", "packages/frontend/Dockerfile", os.environ.get("FRONTEND") == "true"),
|
|
("backend", "packages/backend/Dockerfile", os.environ.get("BACKEND") == "true"),
|
|
("remote-gateway", "packages/remote-gateway/Dockerfile", os.environ.get("REMOTE_GATEWAY") == "true"),
|
|
]
|
|
|
|
include = [
|
|
{"service": service, "dockerfile": dockerfile}
|
|
for service, dockerfile, changed in services
|
|
if shared or changed
|
|
]
|
|
|
|
output_path = Path(os.environ["GITHUB_OUTPUT"])
|
|
with output_path.open("a", encoding="utf-8") as output:
|
|
output.write(f"matrix={json.dumps({'include': include})}\n")
|
|
output.write(f"has_changes={'true' if include else 'false'}\n")
|
|
PY
|
|
|
|
publish:
|
|
needs: detect-changes
|
|
if: needs.detect-changes.outputs.has_changes == 'true'
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix: ${{ fromJson(needs.detect-changes.outputs.matrix) }}
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Log in to GitHub Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract Docker metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/nexus-terminal-${{ matrix.service }}
|
|
tags: |
|
|
type=raw,value=latest
|
|
type=sha,format=short,prefix=sha-
|
|
|
|
- name: Build and push ${{ matrix.service }}
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: ${{ matrix.dockerfile }}
|
|
platforms: linux/amd64
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max,scope=${{ matrix.service }}
|