Skip to content

Commit 2da7731

Browse files
authored
Refactor 2025: unified multi-distro Dockerfile, entrypoint, CI hardening
Merges the refac-2025 branch. See PR comments for full change summary.
2 parents a1af71e + 5ab7240 commit 2da7731

6 files changed

Lines changed: 566 additions & 198 deletions

File tree

.github/workflows/docker-publish.yml

Lines changed: 165 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -4,190 +4,205 @@ on:
44
schedule:
55
- cron: '31 16 * * 1'
66
workflow_dispatch:
7+
push:
8+
branches: [main]
9+
paths:
10+
- 'Dockerfile'
11+
- '.github/workflows/docker-publish.yml'
12+
pull_request:
13+
branches: [main]
14+
paths:
15+
- 'Dockerfile'
16+
- '.github/workflows/docker-publish.yml'
717

8-
jobs:
9-
Alpine:
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: true
1021

22+
jobs:
23+
build:
1124
runs-on: ubuntu-latest
25+
strategy:
26+
matrix:
27+
distro: [alpine, debian]
28+
include:
29+
- distro: alpine
30+
is_latest: true
31+
distro_version: 'latest'
32+
- distro: debian
33+
is_latest: false
34+
debian_version: 'stable-slim'
1235
permissions:
13-
contents: write
36+
contents: read
1437
packages: write
1538
security-events: write
16-
39+
id-token: write # For OIDC auth
40+
1741
steps:
18-
-
19-
name: Docker Setup QEMU
20-
uses: docker/setup-qemu-action@v4
21-
id: qemu
22-
with:
23-
platforms: amd64,arm64,arm
24-
-
25-
name: Docker Setup Buildx
26-
id: buildx
27-
uses: docker/setup-buildx-action@v4
28-
-
29-
name: Login to DockerHub
30-
uses: docker/login-action@v4
31-
with:
32-
username: ${{ secrets.DOCKERHUB_USERNAME }}
33-
password: ${{ secrets.DOCKERHUB_TOKEN }}
34-
-
35-
name: Log into ghcr.io registry
36-
uses: docker/login-action@v4
37-
with:
38-
registry: ghcr.io
39-
username: ${{ github.repository_owner }}
40-
password: ${{ secrets.GITHUB_TOKEN }}
41-
-
42-
name: Login to Quay.io
43-
uses: docker/login-action@v4
44-
with:
45-
registry: quay.io
46-
username: ${{ secrets.QUAY_USERNAME }}
47-
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
48-
-
49-
name: Build and test docker image
50-
uses: docker/build-push-action@v7
51-
with:
52-
# context: .
53-
file: ./Dockerfile.alpine
54-
load: true
55-
tags: docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:alpine-test
56-
cache-from: type=gha
57-
cache-to: type=gha,mode=max
58-
-
59-
name: Test
60-
run: |
61-
docker run --rm docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:alpine-test doxygen --help
62-
-
63-
name: Retrieve doxygen version
64-
run: |
65-
echo "doxygen_version=$(docker run --rm docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:alpine-test doxygen -v)" >> $GITHUB_OUTPUT
66-
id: version
67-
# ${{ steps.version.outputs.doxygen_version }}
68-
-
69-
name: Run Trivy vulnerability scanner
70-
uses: aquasecurity/trivy-action@master
71-
with:
72-
scan-type: image
73-
image-ref: docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:alpine-test
74-
format: 'sarif'
75-
output: 'trivy-results-alpine.sarif'
76-
severity: 'MEDIUM,CRITICAL,HIGH'
77-
hide-progress: false
78-
-
79-
name: Upload Trivy scan results to GitHub Security tab
80-
uses: github/codeql-action/upload-sarif@v4
81-
with:
82-
sarif_file: 'trivy-results-alpine.sarif'
83-
-
84-
name: Build and push Docker image
85-
uses: docker/build-push-action@v7
86-
with:
87-
# context: .
88-
file: ./Dockerfile.alpine
89-
platforms: linux/amd64,linux/arm64,linux/arm/v7
90-
push: true
91-
cache-from: type=gha
92-
cache-to: type=gha,mode=max
93-
tags: |
94-
ghcr.io/kingpin/${{ github.event.repository.name }}:latest
95-
ghcr.io/kingpin/${{ github.event.repository.name }}:alpine
96-
ghcr.io/kingpin/${{ github.event.repository.name }}:alpine-${{ steps.version.outputs.doxygen_version }}
97-
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:latest
98-
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:alpine
99-
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:alpine-${{ steps.version.outputs.doxygen_version }}
100-
quay.io/kingpinx1/${{ github.event.repository.name }}:latest
101-
quay.io/kingpinx1/${{ github.event.repository.name }}:alpine
102-
quay.io/kingpinx1/${{ github.event.repository.name }}:alpine-${{ steps.version.outputs.doxygen_version }}
103-
Debian:
42+
- name: Checkout code
43+
uses: actions/checkout@v4
10444

105-
runs-on: ubuntu-latest
106-
permissions:
107-
contents: write
108-
packages: write
109-
security-events: write
45+
- name: Validate entrypoint syntax
46+
run: sh -n entrypoint.sh
11047

111-
steps:
112-
-
113-
name: Docker Setup QEMU
48+
- name: Set up Docker Buildx
49+
uses: docker/setup-buildx-action@v4
50+
51+
- name: Set up QEMU
11452
uses: docker/setup-qemu-action@v4
115-
id: qemu
11653
with:
117-
platforms: amd64,arm64,arm
118-
-
119-
name: Docker Setup Buildx
120-
id: buildx
121-
uses: docker/setup-buildx-action@v4
122-
-
123-
name: Login to DockerHub
124-
uses: docker/login-action@v4
54+
platforms: linux/amd64,linux/arm64,linux/arm/v7
55+
56+
# Login to Docker Hub
57+
- name: Login to Docker Hub
58+
if: github.event_name != 'pull_request'
59+
uses: docker/login-action@v4
12560
with:
12661
username: ${{ secrets.DOCKERHUB_USERNAME }}
12762
password: ${{ secrets.DOCKERHUB_TOKEN }}
128-
-
129-
name: Log into ghcr.io registry
63+
64+
# Login to GitHub Container Registry
65+
- name: Login to GitHub Container Registry
13066
uses: docker/login-action@v4
13167
with:
13268
registry: ghcr.io
13369
username: ${{ github.repository_owner }}
13470
password: ${{ secrets.GITHUB_TOKEN }}
135-
-
136-
name: Login to Quay.io
71+
72+
# Login to Quay.io
73+
- name: Login to Quay.io
74+
if: github.event_name != 'pull_request'
13775
uses: docker/login-action@v4
13876
with:
13977
registry: quay.io
14078
username: ${{ secrets.QUAY_USERNAME }}
14179
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
142-
-
143-
name: Build and test docker image
80+
81+
# Generate Dockerfile hash
82+
- name: Generate Dockerfile hash
83+
id: hash
84+
run: |
85+
echo "hash=$(sha256sum Dockerfile | cut -d ' ' -f 1)" >> $GITHUB_OUTPUT
86+
87+
# Build test image
88+
- name: Build test image
14489
uses: docker/build-push-action@v7
14590
with:
146-
# context: .
147-
file: ./Dockerfile.debian
91+
context: .
92+
file: ./Dockerfile
93+
build-args: |
94+
DISTRO=${{ matrix.distro }}
95+
${{ matrix.distro == 'alpine' && format('DISTRO_VERSION={0}', matrix.distro_version) || format('DEBIAN_VERSION={0}', matrix.debian_version) }}
14896
load: true
149-
tags: docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:debian-test
150-
cache-from: type=gha
151-
cache-to: type=gha,mode=max
152-
-
153-
name: Test
154-
run: |
155-
docker run --rm docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:debian-test doxygen --help
156-
-
157-
name: Retrieve doxygen version
97+
tags: doxygen-test:${{ matrix.distro }}
98+
cache-from: |
99+
type=gha,scope=${{ matrix.distro }}-${{ steps.hash.outputs.hash }}
100+
type=registry,ref=ghcr.io/kingpin/${{ github.event.repository.name }}:${{ matrix.distro }}-cache
101+
cache-to: |
102+
type=gha,scope=${{ matrix.distro }}-${{ steps.hash.outputs.hash }},mode=max
103+
${{ github.ref == 'refs/heads/main' && format('type=registry,ref=ghcr.io/kingpin/{0}:{1}-cache,mode=max', github.event.repository.name, matrix.distro) || '' }}
104+
105+
# Test image
106+
- name: Test image
158107
run: |
159-
echo "doxygen_version=$(docker run --rm docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:debian-test doxygen -v)" >> $GITHUB_OUTPUT
108+
docker run --rm doxygen-test:${{ matrix.distro }} doxygen --help
109+
110+
# Get Doxygen version
111+
- name: Extract Doxygen version
160112
id: version
161-
# ${{ steps.version.outputs.doxygen_version }}
162-
-
163-
name: Run Trivy vulnerability scanner
164-
uses: aquasecurity/trivy-action@master
113+
run: |
114+
# Run with environment variable to silence entrypoint output
115+
echo "doxygen_version=$(docker run --rm doxygen-test:${{ matrix.distro }} doxygen -v | tail -n1 | tr -d '\n')" >> $GITHUB_OUTPUT
116+
117+
# Verify that we got a clean version
118+
if ! [[ $(cat $GITHUB_OUTPUT | grep doxygen_version | cut -d= -f2) =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
119+
echo "Error: Invalid Doxygen version extracted. Check entrypoint script output."
120+
cat $GITHUB_OUTPUT
121+
exit 1
122+
fi
123+
124+
# Vulnerability scan
125+
- name: Run Trivy vulnerability scanner
126+
uses: aquasecurity/trivy-action@0.30.0
165127
with:
166128
scan-type: image
167-
image-ref: docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:debian-test
129+
image-ref: doxygen-test:${{ matrix.distro }}
168130
format: 'sarif'
169-
output: 'trivy-results-debian.sarif'
131+
output: 'trivy-results-${{ matrix.distro }}.sarif'
170132
severity: 'MEDIUM,CRITICAL,HIGH'
171133
hide-progress: false
172-
-
173-
name: Upload Trivy scan results to GitHub Security tab
174-
uses: github/codeql-action/upload-sarif@v4
175-
with:
176-
sarif_file: 'trivy-results-debian.sarif'
177-
-
178-
name: Build and push Docker image
134+
135+
# Upload scan results
136+
- name: Upload Trivy scan results
137+
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
138+
uses: github/codeql-action/upload-sarif@v3
139+
with:
140+
sarif_file: 'trivy-results-${{ matrix.distro }}.sarif'
141+
142+
# Generate tag lists based on context
143+
- name: Prepare tags
144+
id: prep
145+
run: |
146+
# Generate current timestamp in ISO 8601 format
147+
echo "timestamp=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
148+
149+
# For PR builds, only create GHCR tags with PR number
150+
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
151+
PR_NUMBER=$(echo "$GITHUB_REF" | awk -F / '{print $3}')
152+
if [ -z "$PR_NUMBER" ]; then
153+
echo "Error: could not extract PR number from GITHUB_REF='$GITHUB_REF'" >&2
154+
exit 1
155+
fi
156+
TAGS="ghcr.io/kingpin/${{ github.event.repository.name }}:${{ matrix.distro }}-pr-${PR_NUMBER}
157+
ghcr.io/kingpin/${{ github.event.repository.name }}:${{ matrix.distro }}-${{ steps.version.outputs.doxygen_version }}-pr-${PR_NUMBER}"
158+
159+
if [ "${{ matrix.is_latest }}" = "true" ]; then
160+
TAGS="$TAGS
161+
ghcr.io/kingpin/${{ github.event.repository.name }}:pr-${PR_NUMBER}"
162+
fi
163+
else
164+
# For main branch, create all registry tags
165+
TAGS="ghcr.io/kingpin/${{ github.event.repository.name }}:${{ matrix.distro }}
166+
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:${{ matrix.distro }}
167+
quay.io/kingpinx1/${{ github.event.repository.name }}:${{ matrix.distro }}
168+
ghcr.io/kingpin/${{ github.event.repository.name }}:${{ matrix.distro }}-${{ steps.version.outputs.doxygen_version }}
169+
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:${{ matrix.distro }}-${{ steps.version.outputs.doxygen_version }}
170+
quay.io/kingpinx1/${{ github.event.repository.name }}:${{ matrix.distro }}-${{ steps.version.outputs.doxygen_version }}"
171+
172+
# Add latest tags if this is the latest version
173+
if [ "${{ matrix.is_latest }}" = "true" ]; then
174+
TAGS="$TAGS
175+
ghcr.io/kingpin/${{ github.event.repository.name }}:latest
176+
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:latest
177+
quay.io/kingpinx1/${{ github.event.repository.name }}:latest"
178+
fi
179+
fi
180+
181+
echo "tags<<EOF" >> $GITHUB_OUTPUT
182+
echo "$TAGS" >> $GITHUB_OUTPUT
183+
echo "EOF" >> $GITHUB_OUTPUT
184+
185+
# Build and push the images
186+
- name: Build and push
179187
uses: docker/build-push-action@v7
180188
with:
181-
# context: .
182-
file: ./Dockerfile.debian
189+
context: .
190+
file: ./Dockerfile
191+
build-args: |
192+
DISTRO=${{ matrix.distro }}
193+
${{ matrix.distro == 'alpine' && format('DISTRO_VERSION={0}', matrix.distro_version) || format('DEBIAN_VERSION={0}', matrix.debian_version) }}
183194
platforms: linux/amd64,linux/arm64,linux/arm/v7
184-
push: true
185-
cache-from: type=gha
186-
cache-to: type=gha,mode=max
187-
tags: |
188-
ghcr.io/kingpin/${{ github.event.repository.name }}:debian
189-
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:debian
190-
quay.io/kingpinx1/${{ github.event.repository.name }}:debian
191-
ghcr.io/kingpin/${{ github.event.repository.name }}:debian-${{ steps.version.outputs.doxygen_version }}
192-
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/${{ github.event.repository.name }}:debian-${{ steps.version.outputs.doxygen_version }}
193-
quay.io/kingpinx1/${{ github.event.repository.name }}:debian-${{ steps.version.outputs.doxygen_version }}
195+
push: ${{ github.ref == 'refs/heads/main' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) }}
196+
tags: ${{ steps.prep.outputs.tags }}
197+
cache-from: |
198+
type=gha,scope=${{ matrix.distro }}
199+
type=registry,ref=ghcr.io/kingpin/${{ github.event.repository.name }}:${{ matrix.distro }}-cache
200+
cache-to: |
201+
type=gha,scope=${{ matrix.distro }},mode=max
202+
${{ github.ref == 'refs/heads/main' && format('type=registry,ref=ghcr.io/kingpin/{0}:{1}-cache,mode=max', github.event.repository.name, matrix.distro) || '' }}
203+
labels: |
204+
org.opencontainers.image.title=${{ github.event.repository.name }}
205+
org.opencontainers.image.description=Doxygen container based on ${{ matrix.distro }}
206+
org.opencontainers.image.version=${{ steps.version.outputs.doxygen_version }}
207+
org.opencontainers.image.created=${{ steps.prep.outputs.timestamp }}
208+
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}

0 commit comments

Comments
 (0)