generated from ublue-os/image-template
-
Notifications
You must be signed in to change notification settings - Fork 0
364 lines (331 loc) · 17 KB
/
build.yml
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
---
name: scheduled build image run
on:
pull_request:
branches:
- main
schedule:
- cron: "05 10 * * *" # 10:05am UTC everyday
push:
branches:
- main
paths-ignore:
- "**.md"
- "**.txt"
- "artifacthub-repo.yml"
- "installer/**"
- "repo_files/**"
- "post_install_files/**"
- "docs/**"
- ".github/workflows/build_iso.yml"
workflow_dispatch:
env:
IMAGE_NAME: "${{ github.event.repository.name }}" # the name of the image produced by this build, matches repo names
IMAGE_FLAVOR: "main" # the flavor of the image produced by this build
IMAGE_DESC: "${{ github.event.repository.description }}" # the description of the image produced by this build, matches repo descriptions
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" # do not edit
BASE_IMAGE_NAME: "bazzite" # the name of the base image
BASE_IMAGE_FLAVOR: "gnome" # the flavor of the base image
FEDORA_MAJOR_VERSION: "41" # do not edit
ARTIFACTHUB_LOGO_URL: "https://avatars.githubusercontent.com/u/120078124?s=200&v=4" # You should put your own image here so that you get a fancy profile image on https://artifacthub.io/!
PULL_IMAGE_REGISTRY: ghcr.io/ublue-os
PUSH_IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
KERNEL_FLAVOR: "bazzite" # the flavor of the kernel
KERNEL_VERSION: "6.12.8-201.bazzite.fc41.x86_64" # the version of the kernel
DEFAULT_TAG: "latest" # the default tag for the image
IS_STABLE_VERSION: "true" # whether the image is a stable version
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.brand_name}}-${{ inputs.stream_name }}
cancel-in-progress: true
jobs:
build_push:
name: Build and push image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
id-token: write
steps:
# Unified environment variables declaration to make things neat.
- name: Define extra environment variables
run: |
echo "CONTAINER_TARGET=${IMAGE_NAME}" >> $GITHUB_ENV
echo "SHA_HEAD_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
echo "KERNEL_FLAVOR=${KERNEL_FLAVOR}" >> $GITHUB_ENV
echo "FEDORA_VERSION=${FEDORA_MAJOR_VERSION}" >> $GITHUB_ENV
# These stage versions are pinned by https://github.com/renovatebot/renovate
- name: Checkout Push to Registry Action
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Get current date
id: date
run: |
# This generates a timestamp like what is defined on the ArtifactHub documentation
# E.G: 2022-02-08T15:38:15Z'
# https://artifacthub.io/docs/topics/repositories/container-images/
# https://linux.die.net/man/1/date
echo "date=$(date -u +%Y\-%m\-%d\T%H\:%M\:%S\Z)" >> $GITHUB_OUTPUT
# Image metadata for https://artifacthub.io/ - This is optional but is highly recommended so we all can get a index of all the custom images
# The metadata by itself is not going to do anything, you choose if you want your image to be on ArtifactHub or not.
- name: Image Metadata
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5
id: metadata
with:
# This generates all the tags for your image, you can add custom tags here too!
# By default, it should generate "latest" and "latest.(date here)".
tags: |
type=raw,value=latest
type=raw,value=latest.{{date 'YYYYMMDD'}}
type=raw,value={{date 'YYYYMMDD'}}
type=sha,enable=${{ github.event_name == 'pull_request' }}
type=ref,event=pr
labels: |
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/refs/heads/main/README.md
org.opencontainers.image.created=${{ steps.date.outputs.date }}
org.opencontainers.image.description=${{ env.IMAGE_DESC }}
org.opencontainers.image.documentation=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/refs/heads/main/README.md
org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/blob/main/Containerfile
org.opencontainers.image.title=${{ env.IMAGE_NAME }}
org.opencontainers.image.url=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
org.opencontainers.image.vendor=${{ github.repository_owner }}
org.opencontainers.image.version=latest
io.artifacthub.package.deprecated=false
io.artifacthub.package.keywords=bootc,ublue,universal-blue
io.artifacthub.package.license=Apache-2.0
io.artifacthub.package.logo-url=${{ env.ARTIFACTHUB_LOGO_URL }}
io.artifacthub.package.prerelease=false
containers.bootc=1
sep-tags: " "
sep-annotations: " "
# This is optional, but if you see that your builds are way too big for the runners, you can enable this by uncommenting the following lines:
- name: Maximize build space
uses: ublue-os/remove-unwanted-software@5a8b0374222a6fffddb1be9516b5fece9483bed0 # v8
with:
remove-codeql: true
# Pulling the main image and rechunking it is necessary to avoid common failures.
- name: Pull main, rechunk images
uses: Wandalen/wretry.action@v3.8.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
# pull the base images used for FROM in Containerfile so
# we can retry on that unfortunately common failure case
sudo podman pull ${{ env.PULL_IMAGE_REGISTRY }}/${{ env.BASE_IMAGE_NAME }}-${{ env.BASE_IMAGE_FLAVOR }}:${{ env.FEDORA_VERSION }}
# Add rechunk as well to remove this source of failure
sudo podman pull ghcr.io/hhd-dev/rechunk:v1.1.1
# Get the source image version.
# This is necessary to generate the primary version key that appears
# in rpm-ostree status, and github.
- name: Get source versions
id: labels
uses: Wandalen/wretry.action@v3.8.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
set -eo pipefail
skopeo inspect docker://${{ env.PULL_IMAGE_REGISTRY }}/${{ env.BASE_IMAGE_NAME }}-${{ env.BASE_IMAGE_FLAVOR }}:${{ env.FEDORA_VERSION }} > source.json
ver=$(jq -r '.Labels["org.opencontainers.image.version"]' source.json)
if [ -z "$ver" ] || [ "null" = "$ver" ]; then
echo "inspected image version must not be empty or null"
exit 1
fi
echo "SOURCE_IMAGE_VERSION=$ver" >> $GITHUB_ENV
# Generate a primary version key that appears
# in rpm-ostree status, and github.
- name: Generate Version
id: generate-version
shell: bash
run: |
# Generate the primary version key that will be stored on os-release,
# shown on the bootloader, and used for the image tag.
UPSTREAM_TAG="${{ env.SOURCE_IMAGE_VERSION }}"
# Remove .0 suffix from upstream tag so we can add our own and
# the wrong one does not end up in the image.
UPSTREAM_TAG="${UPSTREAM_TAG%.*}"
FEDORA_VERSION="${{ env.FEDORA_VERSION }}"
SHA_SHORT="${GITHUB_SHA::7}"
if [ -n "${{ github.event.pull_request.number }}" ]; then
VERSION="pr-${FEDORA_VERSION}-${{ github.event.pull_request.number }}"
PRETTY_VERSION="PR (${{ github.event.pull_request.number }}, ${UPSTREAM_TAG})"
elif [[ ${{ github.ref_name }} == "unstable" ]]; then
VERSION="unstable-${UPSTREAM_TAG}"
PRETTY_VERSION="Unstable (F${UPSTREAM_TAG}, #${SHA_SHORT})"
elif [[ ${{ github.ref_name }} == "testing" ]]; then
VERSION="testing-${UPSTREAM_TAG}"
PRETTY_VERSION="Testing (F${UPSTREAM_TAG}, #${SHA_SHORT})"
else
VERSION="${UPSTREAM_TAG}"
PRETTY_VERSION="Stable (F${UPSTREAM_TAG})"
fi
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
echo "pretty=${PRETTY_VERSION}" >> $GITHUB_OUTPUT
echo "Generated the following:"
cat $GITHUB_OUTPUT
# Build image using buildah and save it to raw-img
- name: Build Image
id: build_image
run: |
sudo buildah build \
--target ${{ env.CONTAINER_TARGET }} \
--build-arg IMAGE_NAME=${{ env.IMAGE_NAME }} \
--build-arg IMAGE_FLAVOR=${{ env.IMAGE_FLAVOR }} \
--build-arg IMAGE_VENDOR=${{ github.repository_owner }} \
--build-arg BASE_IMAGE_NAME=${{ env.BASE_IMAGE_NAME }} \
--build-arg BASE_IMAGE_FLAVOR=${{ env.BASE_IMAGE_FLAVOR }} \
--build-arg FEDORA_VERSION=${{ env.FEDORA_MAJOR_VERSION }} \
--build-arg KERNEL_FLAVOR=${{ env.KERNEL_FLAVOR }} \
--build-arg KERNEL_VERSION=${{ env.KERNEL_VERSION }} \
--build-arg IMAGE_BRANCH=${{ github.ref_name }} \
--build-arg SHA_HEAD_SHORT=${{ env.SHA_HEAD_SHORT }} \
--build-arg VERSION_TAG=${{ steps.generate-version.outputs.tag }} \
--build-arg VERSION_PRETTY="${{ steps.generate-version.outputs.pretty }}" \
--tag ${{ env.IMAGE_NAME }} .
# Remove auxiliary images.
- name: Remove auxiliary images
# We are tight on space, need at least 2x for OSTree
run: |
sudo podman image rm ${{ env.PULL_IMAGE_REGISTRY }}/${{ env.BASE_IMAGE_NAME }}-${{ env.BASE_IMAGE_FLAVOR }}:${{ env.FEDORA_VERSION }}
# Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
# https://github.com/macbre/push-to-ghcr/issues/12
# Need to lowercase the registry before doing rechunk.
- name: Lowercase Registry
id: registry_case
uses: ASzc/change-string-case-action@v6
with:
string: ${{ env.IMAGE_REGISTRY }}
# We're using certs from Universal Blue's repo to check the kernel signature.
# https://github.com/ublue-os/kernel-cache
#
- name: Check Secureboot
shell: bash
run: |
set -x
if [[ ! $(command -v sbverify) || ! $(command -v curl) || ! $(command -v openssl) ]]; then
sudo apt update
sudo apt install sbsigntool curl openssl
fi
TMP=$(sudo podman create localhost/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }} bash)
sudo podman cp $TMP:/usr/lib/modules/${{ env.KERNEL_VERSION }}/vmlinuz .
sudo podman rm $TMP
sudo chmod 666 vmlinuz # might not be needed
sbverify --list vmlinuz
curl --retry 3 -Lo kernel-sign.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key.der
curl --retry 3 -Lo akmods.der https://github.com/ublue-os/kernel-cache/raw/main/certs/public_key_2.der
openssl x509 -in kernel-sign.der -out kernel-sign.crt
openssl x509 -in akmods.der -out akmods.crt
sbverify --cert kernel-sign.crt vmlinuz || exit 1
sbverify --cert akmods.crt vmlinuz || exit 1
# Rechunk is a script that we use on Universal Blue to make sure there isnt a single huge layer when your image gets published.
# This does not make your image faster to download, just provides better resumability and fixes a few errors.
# Documentation for Rechunk is provided on their github repository at https://github.com/hhd-dev/rechunk
# You can enable it by uncommenting the following lines:
- name: Run Rechunker
id: rechunk
uses: hhd-dev/rechunk@v1.1.3
with:
rechunk: "ghcr.io/hhd-dev/rechunk:v1.1.2"
ref: "localhost/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
prev-ref: "${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
skip_compression: true
version: ${{ env.FEDORA_MAJOR_VERSION }}
labels: ${{ steps.metadata.outputs.labels }} # Rechunk strips out all the labels during build, this needs to be reapplied here with newline separator
# Generate tags after rechunker runs and checks the primary tag is not duplicated
# If it is, rechunk will suffix it by .1, .2, etc and put it in steps.rechunk.outputs.version
- name: Generate tags
id: generate-tags
shell: bash
run: |
# Common vars for generating tags
VERSION_TAG="${{ steps.rechunk.outputs.version }}"
UPSTREAM_TAG="${{ env.SOURCE_IMAGE_VERSION }}"
FEDORA_VERSION="${{ env.FEDORA_VERSION }}"
SHA_SHORT="${GITHUB_SHA::7}"
BUILD_TAGS=( "${VERSION_TAG}" )
# Use latest var to check if we should tag as latest
unset LATEST
if [[ "${{ env.IS_STABLE_VERSION }}" == "true" ]] && \
[[ "${{ env.IS_STABLE_VERSION }}" == "true" ]]; then
LATEST="1"
fi
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
# Track latest ver per PR
if [ -n "$LATEST" ]; then
BUILD_TAGS+=("pr-${{ github.event.pull_request.number }}")
fi
elif [[ ${{ github.ref_name }} == "unstable" ]]; then
# Per fedora version
BUILD_TAGS+=("${FEDORA_VERSION}-unstable")
BUILD_TAGS+=("unstable-${FEDORA_VERSION}") # flip ver to be last
if [ -n "$LATEST" ]; then
BUILD_TAGS+=("unstable")
fi
elif [[ ${{ github.ref_name }} == "testing" ]]; then
# Per fedora version
BUILD_TAGS+=("${FEDORA_VERSION}-testing")
BUILD_TAGS+=("testing-${FEDORA_VERSION}") # flip ver to be last
if [ -n "$LATEST" ]; then
BUILD_TAGS+=("testing")
fi
else
BUILD_TAGS+=("${FEDORA_VERSION}")
BUILD_TAGS+=("stable-${VERSION_TAG}")
# Per fedora version
BUILD_TAGS+=("${FEDORA_VERSION}-stable")
BUILD_TAGS+=("stable-${FEDORA_VERSION}") # flip ver to be last
if [ -n "$LATEST" ]; then
BUILD_TAGS+=("latest" "stable")
fi
fi
echo "Generated the following build tags: "
for TAG in "${BUILD_TAGS[@]}"; do
echo "${TAG}"
done
echo "alias_tags=${BUILD_TAGS[*]}" >> $GITHUB_OUTPUT
# These `if` statements are so that pull requests for your custom images do not make it publish any packages under your name without you knowing
# They also check if the runner is on the default branch so that things like the merge queue (if you enable it), are going to work
- name: Login to GitHub Container Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Push the image to GHCR (Image Registry)
- name: Push To GHCR
uses: Wandalen/wretry.action@v3.8.0
id: push
if: github.event_name != 'pull_request'
with:
attempt_limit: 3
attempt_delay: 15000
command: |
echo "${{ secrets.GITHUB_TOKEN }}" | sudo podman login ghcr.io -u ${{ github.actor }} --password-stdin
for tag in ${{ steps.generate-tags.outputs.alias_tags }}; do
sudo skopeo copy ${{ steps.rechunk.outputs.ref }} docker://${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}:$tag
done
# Generate digest for Image.
- name: Get Image Digest
id: digest
run: |
# Get digest for signing
DIGEST=$(sudo skopeo inspect --format '{{.Digest}}' ${{ steps.rechunk.outputs.ref }})
echo "Digest is: $DIGEST"
echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
# This section is optional and only needs to be enabled if you plan on distributing
# your project for others to consume. You will need to create a public and private key
# using Cosign and save the private key as a repository secret in Github for this workflow
# to consume. For more details, review the image signing section of the README.
- name: Install Cosign
uses: sigstore/cosign-installer@c56c2d3e59e4281cc41dea2217323ba5694b171e # v3.8.0
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
# Sign the image.
- name: Sign container image
uses: EyeCantCU/cosign-action/sign@v0.3.0
if: github.event_name != 'pull_request'
with:
containers: ${{ env.IMAGE_NAME }}
registry-token: ${{ secrets.GITHUB_TOKEN }}
signing-secret: ${{ secrets.SIGNING_SECRET }}
tags: ${{ steps.digest.outputs.digest }}
registry: ${{ env.PUSH_IMAGE_REGISTRY }}