-
Notifications
You must be signed in to change notification settings - Fork 490
218 lines (197 loc) · 9.99 KB
/
ci-container.yml
File metadata and controls
218 lines (197 loc) · 9.99 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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
name: ci-container
on:
workflow_call:
inputs:
buildtime-base:
description: The Docker image to use as the Go build base
required: true
type: string
runtime-base:
description: The Docker image to use as the container runtime base
required: true
type: string
secrets:
DOCKERHUB_USERNAME:
required: true
DOCKERHUB_TOKEN:
required: true
permissions:
contents: read
id-token: write
attestations: write
jobs:
# Builds and pushes the container image for branch pushes, PRs, and release tags.
# On tag events, also signs the image and attests a signed SBOM to DockerHub via cosign.
ci-build-container:
name: ci-build-container
runs-on: ubuntu-latest
steps:
# Check out the repository so the Dockerfile and source are available to the build.
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Register QEMU emulators so Docker Buildx can build non-native architectures (arm, s390x, etc).
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
# Create a multi-platform-capable Buildx builder instance on the runner.
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
# Authenticate to DockerHub so subsequent push steps and cosign attestation pushes succeed.
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# Install cosign once for all tag-based signing and attestation steps below.
# Uses keyless signing — no private key required; identity is proven via the GitHub Actions
# OIDC token issued to this workflow, rooted in Sigstore Fulcio and logged in Rekor.
- name: Install cosign
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
# Parse the branch name from GITHUB_REF for use as the image tag on non-tag branch pushes.
- name: Extract branch from github ref - New Push
if: ${{ startsWith(github.ref, 'refs/tags/v') != true && github.event_name != 'pull_request' }}
shell: bash
run: echo "branch=${GITHUB_REF#refs/heads/}" >> "$GITHUB_OUTPUT"
id: extract_branch
# Parse the version tag from GITHUB_REF for use as the image tag on tag pushes.
- name: Extract tag from github ref - New Release
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
shell: bash
run: echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
id: extract_tag
# Build and push a multi-arch image tagged with the branch name on direct pushes to tracked
# branches (master, v*, prep-v*). Not run on PRs or tag pushes.
- name: Build and push - New Push
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
if: ${{ startsWith(github.ref, 'refs/tags/v') != true && github.event_name != 'pull_request' }}
with:
context: .
platforms: |
linux/amd64
linux/arm64
linux/arm/v7
linux/s390x
linux/ppc64le
push: true
build-args: |
BUILDTIME_BASE=${{ inputs.buildtime-base }}
RUNTIME_BASE=${{ inputs.runtime-base }}
tags: cloudnativelabs/kube-router-git:${{ steps.extract_branch.outputs.branch }}
# Build and push a single-arch (amd64) image tagged with the PR number for pull requests.
# Multi-arch is skipped here as it adds 30+ minutes to PR feedback time.
- name: Build and push - New PR
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
if: github.event_name == 'pull_request'
with:
context: .
platforms: linux/amd64
push: true
provenance: false
build-args: |
BUILDTIME_BASE=${{ inputs.buildtime-base }}
RUNTIME_BASE=${{ inputs.runtime-base }}
tags: cloudnativelabs/kube-router-git:PR-${{ github.event.pull_request.number }}
# -----------------------------------------------------------------------------------------
# Release Candidate tag (e.g. v2.8.0-rc1): build, sign, generate SBOM, and attest to registry.
# The `latest` tag is NOT updated for release candidates.
# -----------------------------------------------------------------------------------------
# Build and push the multi-arch release candidate image. The step id captures the digest
# so subsequent signing and attestation steps can reference the exact immutable image.
- name: Build and push - New Tag (Release Candidate)
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
id: push_rc
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-rc') }}
with:
context: .
platforms: |
linux/amd64
linux/arm64
linux/arm/v7
linux/s390x
linux/ppc64le
push: true
build-args: |
BUILDTIME_BASE=${{ inputs.buildtime-base }}
RUNTIME_BASE=${{ inputs.runtime-base }}
tags: |
cloudnativelabs/kube-router:${{ steps.extract_tag.outputs.tag }}
# Sign the RC image digest with cosign (keyless). The signature is pushed to DockerHub as a
# sibling OCI artifact and the signing event is recorded in the Rekor transparency log.
# Verify with: cosign verify --certificate-identity-regexp "https://github.com/cloudnativelabs/.*"
# --certificate-oidc-issuer "https://token.actions.githubusercontent.com"
# cloudnativelabs/kube-router:<rc-tag>
- name: Sign container image - New Tag (Release Candidate)
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-rc') }}
run: cosign sign --yes cloudnativelabs/kube-router@${{ steps.push_rc.outputs.digest }}
# Generate an SPDX-JSON SBOM for the RC image using Syft. The SBOM is written to a local
# file for the attestation step and also uploaded as a workflow artifact.
- name: Generate SBOM for container image - New Tag (Release Candidate)
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
id: sbom_rc
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-rc') }}
with:
image: cloudnativelabs/kube-router@${{ steps.push_rc.outputs.digest }}
format: spdx-json
artifact-name: kube-router-${{ github.ref_name }}-image-sbom.spdx.json
output-file: ./container-sbom-rc.spdx.json
# Wrap the SBOM in a signed in-toto attestation and push it to DockerHub alongside the image.
# Users can retrieve and verify it with:
# cosign verify-attestation --type spdxjson
# --certificate-identity-regexp "https://github.com/cloudnativelabs/.*"
# --certificate-oidc-issuer "https://token.actions.githubusercontent.com"
# cloudnativelabs/kube-router:<rc-tag> | jq -r '.payload' | base64 -d | jq '.predicate'
- name: Attest SBOM to container image - New Tag (Release Candidate)
if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-rc') }}
run: |
cosign attest --yes \
--predicate ./container-sbom-rc.spdx.json \
--type spdxjson \
cloudnativelabs/kube-router@${{ steps.push_rc.outputs.digest }}
# -----------------------------------------------------------------------------------------
# Production release tag (e.g. v2.8.0): build, sign, generate SBOM, and attest to registry.
# Both the versioned tag and `latest` are updated.
# -----------------------------------------------------------------------------------------
# Build and push the multi-arch production release image. Updates both the versioned tag and
# `latest`. The step id captures the digest for signing and attestation.
- name: Build and push - New Tag
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
id: push_release
if: ${{ startsWith(github.ref, 'refs/tags/v') && ! contains(github.ref, '-rc') }}
with:
context: .
platforms: |
linux/amd64
linux/arm64
linux/arm/v7
linux/s390x
linux/ppc64le
push: true
build-args: |
BUILDTIME_BASE=${{ inputs.buildtime-base }}
RUNTIME_BASE=${{ inputs.runtime-base }}
tags: |
cloudnativelabs/kube-router:${{ steps.extract_tag.outputs.tag }}
cloudnativelabs/kube-router:latest
# Sign the production release image digest with cosign (keyless). Same verification command
# as the RC step above, using the production release tag.
- name: Sign container image - New Tag
if: ${{ startsWith(github.ref, 'refs/tags/v') && ! contains(github.ref, '-rc') }}
run: cosign sign --yes cloudnativelabs/kube-router@${{ steps.push_release.outputs.digest }}
# Generate an SPDX-JSON SBOM for the production release image using Syft.
- name: Generate SBOM for container image - New Tag
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
id: sbom_release
if: ${{ startsWith(github.ref, 'refs/tags/v') && ! contains(github.ref, '-rc') }}
with:
image: cloudnativelabs/kube-router@${{ steps.push_release.outputs.digest }}
format: spdx-json
artifact-name: kube-router-${{ github.ref_name }}-image-sbom.spdx.json
output-file: ./container-sbom-release.spdx.json
# Wrap the SBOM in a signed in-toto attestation and push it to DockerHub alongside the image.
- name: Attest SBOM to container image - New Tag
if: ${{ startsWith(github.ref, 'refs/tags/v') && ! contains(github.ref, '-rc') }}
run: |
cosign attest --yes \
--predicate ./container-sbom-release.spdx.json \
--type spdxjson \
cloudnativelabs/kube-router@${{ steps.push_release.outputs.digest }}