Skip to content

Commit 4bf99ab

Browse files
authored
Initial commit
0 parents  commit 4bf99ab

File tree

14 files changed

+1223
-0
lines changed

14 files changed

+1223
-0
lines changed

.github/dependabot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "github-actions"
9+
directory: "/"
10+
schedule:
11+
interval: "weekly"

.github/renovate.json5

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
3+
"extends": [
4+
"config:best-practices",
5+
],
6+
7+
"rebaseWhen": "never",
8+
9+
"packageRules": [
10+
{
11+
"automerge": true,
12+
"matchUpdateTypes": ["pin", "pinDigest"]
13+
},
14+
{
15+
"enabled": false,
16+
"matchUpdateTypes": ["digest", "pinDigest", "pin"],
17+
"matchDepTypes": ["container"],
18+
"matchFileNames": [".github/workflows/**.yaml", ".github/workflows/**.yml"],
19+
},
20+
]
21+
}

.github/workflows/build-disk.yml

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
name: Build disk images
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
upload-to-s3:
8+
description: "Upload to S3"
9+
required: false
10+
default: false
11+
type: boolean
12+
platform:
13+
required: true
14+
type: choice
15+
options:
16+
- amd64
17+
- arm64
18+
pull_request:
19+
branches:
20+
- main
21+
paths:
22+
- './disk_config/disk.toml'
23+
- './disk_config/iso.toml'
24+
- './.github/workflows/build-disk.yml'
25+
26+
env:
27+
IMAGE_NAME: ${{ github.event.repository.name }} # output of build.yml, keep in sync
28+
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" # do not edit
29+
DEFAULT_TAG: "latest"
30+
BIB_IMAGE: "ghcr.io/lorbuschris/bootc-image-builder:20250608" # "quay.io/centos-bootc/bootc-image-builder:latest" - see https://github.com/osbuild/bootc-image-builder/pull/954
31+
32+
concurrency:
33+
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
34+
cancel-in-progress: true
35+
36+
jobs:
37+
build:
38+
name: Build disk images
39+
runs-on: ${{ inputs.platform == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }}
40+
strategy:
41+
fail-fast: false
42+
matrix:
43+
disk-type: ["qcow2", "anaconda-iso"]
44+
permissions:
45+
contents: read
46+
packages: read
47+
id-token: write
48+
49+
steps:
50+
- name: Prepare environment
51+
run: |
52+
USER_UID=$(id -u)
53+
USER_GID=$(id -g)
54+
# Concatenate the types with a hyphen
55+
DISK_TYPE=$(echo "${{ matrix.disk-type }}" | tr ' ' '-')
56+
# Lowercase the image uri
57+
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
58+
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
59+
echo "DISK_TYPE=${DISK_TYPE}" >> ${GITHUB_ENV}
60+
echo "USER_UID=${USER_UID}" >> ${GITHUB_ENV}
61+
echo "USER_GID=${USER_GID}" >> ${GITHUB_ENV}
62+
63+
- name: Install dependencies
64+
if: inputs.platform == 'arm64'
65+
run: |
66+
set -x
67+
sudo apt update -y
68+
sudo apt install -y \
69+
podman
70+
71+
- name: Maximize build space
72+
if: inputs.platform != 'arm64'
73+
uses: ublue-os/remove-unwanted-software@cc0becac701cf642c8f0a6613bbdaf5dc36b259e # v9
74+
with:
75+
remove-codeql: true
76+
77+
- name: Checkout
78+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
79+
80+
- name: Build disk images
81+
id: build
82+
uses: osbuild/bootc-image-builder-action@main
83+
with:
84+
builder-image: ${{ env.BIB_IMAGE }}
85+
config-file: ${{ matrix.disk-type == 'anaconda-iso' && './disk_config/iso.toml' || './disk_config/disk.toml' }}
86+
image: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}
87+
chown: ${{ env.USER_UID }}:${{ env.USER_GID }}
88+
types: ${{ matrix.disk-type }}
89+
additional-args: --use-librepo=True
90+
91+
- name: Upload disk images and Checksum to Job Artifacts
92+
if: inputs.upload-to-s3 != true && github.event_name != 'pull_request'
93+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
94+
with:
95+
path: ${{ steps.build.outputs.output-directory }}
96+
if-no-files-found: error
97+
retention-days: 0
98+
compression-level: 0
99+
overwrite: true
100+
101+
- name: Upload to S3
102+
if: inputs.upload-to-s3 == true && github.event_name != 'pull_request'
103+
shell: bash
104+
env:
105+
RCLONE_CONFIG_S3_TYPE: s3
106+
RCLONE_CONFIG_S3_PROVIDER: ${{ secrets.S3_PROVIDER }}
107+
RCLONE_CONFIG_S3_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
108+
RCLONE_CONFIG_S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
109+
RCLONE_CONFIG_S3_REGION: ${{ secrets.S3_REGION }}
110+
RCLONE_CONFIG_S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
111+
SOURCE_DIR: ${{ steps.build.outputs.output-directory }}
112+
run: |
113+
sudo apt-get update
114+
sudo apt-get install -y rclone
115+
rclone copy $SOURCE_DIR S3:${{ secrets.S3_BUCKET_NAME }}

.github/workflows/build.yml

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
---
2+
name: Build container image
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
schedule:
8+
- cron: '05 10 * * *' # 10:05am UTC everyday
9+
push:
10+
branches:
11+
- main
12+
paths-ignore:
13+
- '**/README.md'
14+
workflow_dispatch:
15+
16+
env:
17+
IMAGE_DESC: "My Customized Universal Blue Image"
18+
IMAGE_KEYWORDS: "bootc,ublue,universal-blue"
19+
IMAGE_LOGO_URL: "https://avatars.githubusercontent.com/u/120078124?s=200&v=4" # Put your own image here for a fancy profile on https://artifacthub.io/!
20+
IMAGE_NAME: "${{ github.event.repository.name }}" # output image name, usually same as repo name
21+
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" # do not edit
22+
DEFAULT_TAG: "latest"
23+
24+
concurrency:
25+
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.brand_name}}-${{ inputs.stream_name }}
26+
cancel-in-progress: true
27+
28+
jobs:
29+
build_push:
30+
name: Build and push image
31+
runs-on: ubuntu-24.04
32+
33+
permissions:
34+
contents: read
35+
packages: write
36+
id-token: write
37+
38+
steps:
39+
- name: Prepare environment
40+
run: |
41+
# Lowercase the image uri
42+
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
43+
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
44+
45+
# These stage versions are pinned by https://github.com/renovatebot/renovate
46+
- name: Checkout
47+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
48+
49+
# 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:
50+
# - name: Maximize build space
51+
# uses: ublue-os/remove-unwanted-software@517622d6452028f266b7ba4cc9a123b5f58a6b53 # v7
52+
# with:
53+
# remove-codeql: true
54+
55+
- name: Mount BTRFS for podman storage
56+
id: container-storage-action
57+
uses: ublue-os/container-storage-action@911baca08baf30c8654933e9e9723cb399892140
58+
59+
# Fallback to the remove-unwanted-software-action if github doesn't allocate enough space
60+
# See: https://github.com/ublue-os/container-storage-action/pull/11
61+
continue-on-error: true
62+
with:
63+
target-dir: /var/lib/containers
64+
mount-opts: compress-force=zstd:2
65+
66+
- name: Get current date
67+
id: date
68+
run: |
69+
# This generates a timestamp like what is defined on the ArtifactHub documentation
70+
# E.G: 2022-02-08T15:38:15Z'
71+
# https://artifacthub.io/docs/topics/repositories/container-images/
72+
# https://linux.die.net/man/1/date
73+
echo "date=$(date -u +%Y\-%m\-%d\T%H\:%M\:%S\Z)" >> $GITHUB_OUTPUT
74+
75+
# 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
76+
# The metadata by itself is not going to do anything, you choose if you want your image to be on ArtifactHub or not.
77+
- name: Image Metadata
78+
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5
79+
id: metadata
80+
with:
81+
# This generates all the tags for your image, you can add custom tags here too!
82+
# Default tags are "$DEFAULT_TAG" and "$DEFAULT_TAG.$date".
83+
tags: |
84+
type=raw,value=${{ env.DEFAULT_TAG }}
85+
type=raw,value=${{ env.DEFAULT_TAG }}.{{date 'YYYYMMDD'}}
86+
type=raw,value={{date 'YYYYMMDD'}}
87+
type=sha,enable=${{ github.event_name == 'pull_request' }}
88+
type=ref,event=pr
89+
labels: |
90+
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/refs/heads/main/README.md
91+
org.opencontainers.image.created=${{ steps.date.outputs.date }}
92+
org.opencontainers.image.description=${{ env.IMAGE_DESC }}
93+
org.opencontainers.image.documentation=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/refs/heads/main/README.md
94+
org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/blob/main/Containerfile
95+
org.opencontainers.image.title=${{ env.IMAGE_NAME }}
96+
org.opencontainers.image.url=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
97+
org.opencontainers.image.vendor=${{ github.repository_owner }}
98+
org.opencontainers.image.version=${{ env.DEFAULT_TAG }}.{{date 'YYYYMMDD'}}
99+
io.artifacthub.package.deprecated=false
100+
io.artifacthub.package.keywords=${{ env.IMAGE_KEYWORDS }}
101+
io.artifacthub.package.license=Apache-2.0
102+
io.artifacthub.package.logo-url=${{ env.IMAGE_LOGO_URL }}
103+
io.artifacthub.package.prerelease=false
104+
containers.bootc=1
105+
sep-tags: " "
106+
sep-annotations: " "
107+
108+
- name: Build Image
109+
id: build_image
110+
uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2
111+
with:
112+
containerfiles: |
113+
./Containerfile
114+
# Postfix image name with -custom to make it a little more descriptive
115+
# Syntax: https://docs.github.com/en/actions/learn-github-actions/expressions#format
116+
image: ${{ env.IMAGE_NAME }}
117+
tags: ${{ steps.metadata.outputs.tags }}
118+
labels: ${{ steps.metadata.outputs.labels }}
119+
oci: false
120+
121+
# Rechunk is a script that we use on Universal Blue to make sure there isnt a single huge layer when your image gets published.
122+
# This does not make your image faster to download, just provides better resumability and fixes a few errors.
123+
# Documentation for Rechunk is provided on their github repository at https://github.com/hhd-dev/rechunk
124+
# You can enable it by uncommenting the following lines:
125+
# - name: Run Rechunker
126+
# id: rechunk
127+
# uses: hhd-dev/rechunk@f153348d8100c1f504dec435460a0d7baf11a9d2 # v1.1.1
128+
# with:
129+
# rechunk: 'ghcr.io/hhd-dev/rechunk:v1.0.1'
130+
# ref: "localhost/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
131+
# prev-ref: "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
132+
# skip_compression: true
133+
# version: ${{ env.CENTOS_VERSION }}
134+
# labels: ${{ steps.metadata.outputs.labels }} # Rechunk strips out all the labels during build, this needs to be reapplied here with newline separator
135+
136+
# This is necessary so that the podman socket can find the rechunked image on its storage
137+
# - name: Load in podman and tag
138+
# run: |
139+
# IMAGE=$(podman pull ${{ steps.rechunk.outputs.ref }})
140+
# sudo rm -rf ${{ steps.rechunk.outputs.output }}
141+
# for tag in ${{ steps.metadata.outputs.tags }}; do
142+
# podman tag $IMAGE ${{ env.IMAGE_NAME }}:$tag
143+
# done
144+
145+
# 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
146+
# 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
147+
- name: Login to GitHub Container Registry
148+
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
149+
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
150+
with:
151+
registry: ghcr.io
152+
username: ${{ github.actor }}
153+
password: ${{ secrets.GITHUB_TOKEN }}
154+
155+
- name: Push To GHCR
156+
uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2
157+
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
158+
id: push
159+
env:
160+
REGISTRY_USER: ${{ github.actor }}
161+
REGISTRY_PASSWORD: ${{ github.token }}
162+
with:
163+
registry: ${{ env.IMAGE_REGISTRY }}
164+
image: ${{ env.IMAGE_NAME }}
165+
tags: ${{ steps.metadata.outputs.tags }}
166+
username: ${{ env.REGISTRY_USER }}
167+
password: ${{ env.REGISTRY_PASSWORD }}
168+
169+
# This section is optional and only needs to be enabled if you plan on distributing
170+
# your project for others to consume. You will need to create a public and private key
171+
# using Cosign and save the private key as a repository secret in Github for this workflow
172+
# to consume. For more details, review the image signing section of the README.
173+
- name: Install Cosign
174+
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
175+
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
176+
177+
- name: Sign container image
178+
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
179+
run: |
180+
IMAGE_FULL="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}"
181+
for tag in ${{ steps.metadata.outputs.tags }}; do
182+
cosign sign -y --key env://COSIGN_PRIVATE_KEY $IMAGE_FULL:$tag
183+
done
184+
env:
185+
TAGS: ${{ steps.push.outputs.digest }}
186+
COSIGN_EXPERIMENTAL: false
187+
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cosign.key
2+
_build_*
3+
output
4+
_build-*/**

Containerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Allow build scripts to be referenced without being copied into the final image
2+
FROM scratch AS ctx
3+
COPY build_files /
4+
5+
# Base Image
6+
FROM ghcr.io/ublue-os/bazzite:stable
7+
8+
## Other possible base images include:
9+
# FROM ghcr.io/ublue-os/bazzite:latest
10+
# FROM ghcr.io/ublue-os/bluefin-nvidia:stable
11+
#
12+
# ... and so on, here are more base images
13+
# Universal Blue Images: https://github.com/orgs/ublue-os/packages
14+
# Fedora base image: quay.io/fedora/fedora-bootc:41
15+
# CentOS base images: quay.io/centos-bootc/centos-bootc:stream10
16+
17+
### MODIFICATIONS
18+
## make modifications desired in your image and install packages by modifying the build.sh script
19+
## the following RUN directive does all the things required to run "build.sh" as recommended.
20+
21+
RUN --mount=type=bind,from=ctx,source=/,target=/ctx \
22+
--mount=type=cache,dst=/var/cache \
23+
--mount=type=cache,dst=/var/log \
24+
--mount=type=tmpfs,dst=/tmp \
25+
/ctx/build.sh
26+
27+
### LINTING
28+
## Verify final image and contents are correct.
29+
RUN bootc container lint

0 commit comments

Comments
 (0)