-
Notifications
You must be signed in to change notification settings - Fork 153
180 lines (158 loc) · 6.83 KB
/
Copy pathdocker-rebuild.yml
File metadata and controls
180 lines (158 loc) · 6.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
name: Rebuild Docker Image on Base Update
on:
schedule:
- cron: '0 7 * * 1' # weekly, Monday 07:00 UTC
workflow_dispatch:
permissions:
contents: read # checkout only; Docker Hub auth uses secrets, not GITHUB_TOKEN
jobs:
check_base_image:
name: Check for base image updates
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
rebuild: ${{ steps.compare.outputs.rebuild }}
upstream_digest: ${{ steps.upstream.outputs.digest }}
release_tag: ${{ steps.release.outputs.tag }}
steps:
- name: Check out the repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
fetch-tags: true
- name: Determine latest release tag
id: release
run: |
TAG=$(git tag --list 'v*' --sort=-version:refname | head -n1)
if [ -z "$TAG" ]; then
echo "No v* release tag found" >&2
exit 1
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Get current upstream base digest
id: upstream
run: |
DIGEST=$(docker buildx imagetools inspect node:lts-alpine --format '{{json .Manifest}}' | jq -r '.digest')
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
- name: Get published image base digest
id: published
run: |
# The label lives in each platform image config; handle single- and multi-platform output shapes.
DIGEST=$(docker buildx imagetools inspect isokoliuk/mcp-searxng:latest --format '{{json .Image}}' \
| jq -r '[.. | objects | select(has("config")) | .config.Labels["org.opencontainers.image.base.digest"] // empty] | first // ""')
echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
- name: Compare digests
id: compare
run: |
UPSTREAM="${{ steps.upstream.outputs.digest }}"
PUBLISHED="${{ steps.published.outputs.digest }}"
echo "Upstream base: $UPSTREAM"
echo "Published base: ${PUBLISHED:-<no base digest label>}"
if [ "$UPSTREAM" != "$PUBLISHED" ]; then
echo "Base image drift detected — rebuild required"
echo "rebuild=true" >> "$GITHUB_OUTPUT"
else
echo "Published image is up to date"
echo "rebuild=false" >> "$GITHUB_OUTPUT"
fi
rebuild_scan:
name: Scan rebuilt Docker image
needs: check_base_image
if: needs.check_base_image.outputs.rebuild == 'true'
runs-on: ubuntu-latest
permissions:
contents: read # checkout only
security-events: write # for Trivy SARIF upload to GitHub Security tab
steps:
- name: Check out latest release tag
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.check_base_image.outputs.release_tag }}
- name: Patch Dockerfile to current upstream base digest
run: |
sed -i -E "s|node:lts-alpine(@sha256:[a-f0-9]{64})?|node:lts-alpine@${{ needs.check_base_image.outputs.upstream_digest }}|g" Dockerfile
echo "Patched FROM lines:"
grep -n '^FROM' Dockerfile
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Build image for vulnerability scan (amd64)
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
load: true
tags: isokoliuk/mcp-searxng:rebuild-scan
- name: Scan rebuilt image for vulnerabilities
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: 'isokoliuk/mcp-searxng:rebuild-scan'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
ignore-unfixed: true
exit-code: '1'
- name: Upload Trivy scan results to Security tab
uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
if: always()
with:
sarif_file: 'trivy-results.sarif'
rebuild_and_publish:
name: Rebuild and republish with updated base
needs:
- check_base_image
- rebuild_scan
if: needs.check_base_image.outputs.rebuild == 'true'
runs-on: ubuntu-latest
permissions:
contents: read # checkout only; Docker Hub auth uses secrets, not GITHUB_TOKEN
id-token: write # for Cosign keyless signing
steps:
- name: Check out latest release tag
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.check_base_image.outputs.release_tag }}
- name: Patch Dockerfile to current upstream base digest
run: |
sed -i -E "s|node:lts-alpine(@sha256:[a-f0-9]{64})?|node:lts-alpine@${{ needs.check_base_image.outputs.upstream_digest }}|g" Dockerfile
echo "Patched FROM lines:"
grep -n '^FROM' Dockerfile
- name: Compute version tags
id: tags
run: |
TAG="${{ needs.check_base_image.outputs.release_tag }}"
VERSION="${TAG#v}"
MAJOR_MINOR="${VERSION%.*}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "major_minor=$MAJOR_MINOR" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0
- name: Log in to Docker Hub
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# A failed Trivy scan (exit-code 1) stops the scan job, blocking the push below.
- name: Build and push multi-arch image
id: publish
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
isokoliuk/mcp-searxng:${{ steps.tags.outputs.version }}
isokoliuk/mcp-searxng:${{ steps.tags.outputs.major_minor }}
isokoliuk/mcp-searxng:latest
labels: |
org.opencontainers.image.base.name=docker.io/library/node:lts-alpine
org.opencontainers.image.base.digest=${{ needs.check_base_image.outputs.upstream_digest }}
- name: Install Cosign
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
with:
cosign-release: 'v3.1.1'
- name: Sign image (keyless OIDC)
env:
DIGEST: ${{ steps.publish.outputs.digest }}
run: cosign sign --yes "docker.io/isokoliuk/mcp-searxng@${DIGEST}"