Repository navigation
Expand file tree
/
Copy pathJustfile
More file actions
215 lines (185 loc) · 9.63 KB
/
Copy pathJustfile
File metadata and controls
215 lines (185 loc) · 9.63 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
# ISO/live/e2e recipes live in iso.justfile (kept separate for readability)
import "iso.justfile"
# List available commands
[group('info')]
default:
@just --list
# ── Configuration ─────────────────────────────────────────────────────
export image_name := env("BUILD_IMAGE_NAME", "tromso")
export image_tag := env("BUILD_IMAGE_TAG", "latest")
export base_dir := env("BUILD_BASE_DIR", ".")
export filesystem := env("BUILD_FILESYSTEM", "ext4")
# Same bst2 container image CI uses -- pinned by SHA for reproducibility
export bst2_image := env("BST2_IMAGE", "registry.gitlab.com/freedesktop-sdk/infrastructure/freedesktop-sdk-docker-images/bst2:64eb0b4930d57a92710822898fb73af6cc1ae35d")
# bst-dashboard (developer tooling for `just dashboard`). Fetched from an
# immutable commit and checked against SHA-256 before it is ever executed, so
# a change to the source repo's branch tip cannot run on a maintainer's
# machine. `tuna-os/buildstream-dashboard` no longer resolves; the script is
# maintained in tuna-os/xfce-linux (tools/). To bump: pick a reviewed commit,
# update the rev and both digests together (sha256sum tools/bst-dashboard.*).
export bst_dashboard_repo := "tuna-os/xfce-linux"
export bst_dashboard_rev := "dc3fbec57d7306ea86cd100ab08b15bd8bb3873e"
export bst_dashboard_py_sha256 := "0a391323cc99a5ad24bfb2fbb40691bdd1f552bbaa6d31502e51cece018137bb"
export bst_dashboard_html_sha256 := "c726069acfa25c80df6a14b336d04f67ab496faf4c76852f7d2a32a902fa84e8"
# VM settings
export vm_ram := env("VM_RAM", "8192")
export vm_cpus := env("VM_CPUS", "4")
# OCI metadata (dynamic labels)
export OCI_IMAGE_CREATED := env("OCI_IMAGE_CREATED", "")
export OCI_IMAGE_REVISION := env("OCI_IMAGE_REVISION", "")
export OCI_IMAGE_VERSION := env("OCI_IMAGE_VERSION", "latest")
import "just/buildstream.just"
import "just/disk-vm.just"
# ── Build ─────────────────────────────────────────────────────────────
[group('build')]
build:
#!/usr/bin/env bash
set -euo pipefail
echo "==> Building Tromso OCI image with BuildStream..."
BST_FLAGS="--no-interactive " just bst build oci/tromso.bst
just export
# ── Export ─────────────────────────────────────────────────────────────
[group('build')]
export:
#!/usr/bin/env bash
set -euo pipefail
SUDO_CMD=""
if [ "$(id -u)" -ne 0 ]; then
SUDO_CMD="sudo"
fi
# CI checks the artifact out in its own step and deletes the CAS before
# calling this recipe: the merged cache and the squashed image do not fit
# on a GitHub runner together. With EXPORT_REUSE_CHECKOUT=1, .build-out is
# already the artifact and must not be re-requested from BuildStream.
if [ "${EXPORT_REUSE_CHECKOUT:-0}" = "1" ]; then
[ -d .build-out ] || { echo "ERROR: EXPORT_REUSE_CHECKOUT=1 but .build-out is missing" >&2; exit 1; }
echo "==> Reusing the existing .build-out checkout..."
else
echo "==> Exporting Tromso OCI image..."
rm -rf .build-out
just bst artifact checkout oci/tromso.bst --directory /src/.build-out
fi
echo "==> Loading and squashing OCI image..."
IMAGE_ID=$($SUDO_CMD podman pull -q oci:.build-out)
rm -rf .build-out
LABEL_ARGS=""
if [ -n "${OCI_IMAGE_CREATED}" ]; then
LABEL_ARGS="${LABEL_ARGS} --label org.opencontainers.image.created=${OCI_IMAGE_CREATED}"
fi
if [ -n "${OCI_IMAGE_REVISION}" ]; then
LABEL_ARGS="${LABEL_ARGS} --label org.opencontainers.image.revision=${OCI_IMAGE_REVISION}"
fi
if [ -n "${OCI_IMAGE_VERSION}" ]; then
LABEL_ARGS="${LABEL_ARGS} --label org.opencontainers.image.version=${OCI_IMAGE_VERSION}"
fi
DATE_TAG="$(date -u +%Y%m%d)"
printf 'FROM %s\nRUN sed -i "s/^VERSION_ID=.*/VERSION_ID=\\"%s\\"/" /usr/lib/os-release \\\n && sed -i "s/^IMAGE_VERSION=.*/IMAGE_VERSION=\\"%s\\"/" /usr/lib/os-release\n' "$IMAGE_ID" "$DATE_TAG" "$DATE_TAG" \
| $SUDO_CMD podman build --pull=never --security-opt label=type:unconfined_t ${LABEL_ARGS} -t "{{image_name}}:{{image_tag}}" -f - .
$SUDO_CMD podman rmi "$IMAGE_ID" || true
echo "==> Export complete: {{image_name}}:{{image_tag}}"
# Chunkify optimises the image for ostree/composefs distribution but may
# fail if the overlay diff layer contains whiteout char devices (issue #20).
# Treat it as non-fatal so GHCR push succeeds even if chunking is skipped.
just chunkify "{{image_name}}:{{image_tag}}" || \
echo "==> Warning: chunkify failed (see issue #20); image will be pushed unchunked"
# ── Clean ─────────────────────────────────────────────────────────────
[group('build')]
clean:
rm -f bootable.raw .ovmf-vars.fd
rm -rf .build-out
# ── Chunkah ──────────────────────────────────────────────────────────
chunkify image_ref:
#!/usr/bin/env bash
set -euo pipefail
SUDO_CMD=""
if [ "$(id -u)" -ne 0 ]; then
SUDO_CMD="sudo"
fi
echo "==> Chunkifying {{image_ref}}..."
CONFIG=$($SUDO_CMD podman inspect "{{image_ref}}")
FAKECAP_RESTORE="{{justfile_directory()}}/files/fakecap/fakecap-restore"
FAKECAP_RESTORE_SRC="{{justfile_directory()}}/files/fakecap/fakecap-restore.c"
FAKECAP_MANIFEST="{{justfile_directory()}}/files/fakecap-manifest.tsv"
# Both inputs are absent from the tree today, so this branch always fires
# and chunkify is a no-op in `just build` and in CI (tromso#277):
#
# - fakecap-restore.c came in with the Dakota assets and was dropped by
# the tromso-iso merge (74465bc) without anyone noticing.
# - fakecap-manifest.tsv was Dakota's *generated* manifest, 67 MB,
# naming bluefin/* and gnomeos* elements this repo does not have. It
# was removed in 0ddf4ee and must not come back: it is build output,
# and it was never correct for a Tromso rootfs anyway.
#
# Reviving chunkify needs a generator that derives the map from Tromso's
# own graph. Do NOT fix this by committing a manifest. See docs/adr/0005.
if [ ! -f "$FAKECAP_RESTORE_SRC" ] || [ ! -f "$FAKECAP_MANIFEST" ]; then
echo "==> Skipping chunkify: missing fakecap inputs ($FAKECAP_RESTORE_SRC, $FAKECAP_MANIFEST)."
echo "==> This is the current steady state, not a transient error — see tromso#277."
exit 0
fi
if [ ! -x "$FAKECAP_RESTORE" ]; then
echo "==> Compiling fakecap-restore..."
gcc -O2 -o "$FAKECAP_RESTORE" "$FAKECAP_RESTORE_SRC"
fi
LOWER=$($SUDO_CMD podman image mount "{{image_ref}}")
cleanup() {
$SUDO_CMD umount "$MERGED" 2>/dev/null || true
$SUDO_CMD rm -rf "$UPPER" "$WORK" "$MERGED"
$SUDO_CMD podman image umount "{{image_ref}}" >/dev/null 2>&1 || true
}
trap cleanup EXIT
UPPER=$(mktemp -d -p /var/tmp)
WORK=$(mktemp -d -p /var/tmp)
MERGED=$(mktemp -d -p /var/tmp)
$SUDO_CMD chmod 755 "$UPPER" "$WORK" "$MERGED"
$SUDO_CMD mount -t overlay overlay \
-o "lowerdir=${LOWER},upperdir=${UPPER},workdir=${WORK}" \
"$MERGED"
echo "==> Applying user.component xattrs via fakecap-restore..."
$SUDO_CMD "$FAKECAP_RESTORE" "$FAKECAP_MANIFEST" "$MERGED"
CHUNKAH_REF="quay.io/coreos/chunkah@sha256:306371251e61cc870c8546e225b13bdf2e333f79461dc5e0fc280cc170cee070"
for attempt in 1 2 3; do
$SUDO_CMD podman pull "$CHUNKAH_REF" && break
echo "==> chunkah pull attempt $attempt failed, retrying in 10s..."
[ "$attempt" -lt 3 ] && sleep 10
done
LOADED=$($SUDO_CMD podman run --rm \
--pull never \
--security-opt label=type:unconfined_t \
-v "${MERGED}:/chunkah:ro" \
-e "CHUNKAH_ROOTFS=/chunkah" \
-e "CHUNKAH_CONFIG_STR=$CONFIG" \
"$CHUNKAH_REF" build --max-layers 120 --prune /sysroot/ \
--label ostree.commit- --label ostree.final-diffid- \
| $SUDO_CMD podman load)
echo "$LOADED"
NEW_REF=$(echo "$LOADED" | sed -n 's/^Loaded image(s): //p; s/^Loaded image: //p' | head -1)
if [ -z "$NEW_REF" ]; then
NEW_REF=$(echo "$LOADED" | grep -oP '^[0-9a-f]{64}$' | head -1 || true)
fi
if [ -n "$NEW_REF" ] && [ "$NEW_REF" != "{{image_ref}}" ]; then
echo "==> Retagging chunked image to {{image_ref}}..."
$SUDO_CMD podman tag "$NEW_REF" "{{image_ref}}"
fi
# ── Unit tests ───────────────────────────────────────────────────────
[group('test')]
test:
#!/usr/bin/env bash
set -euo pipefail
echo "==> Running BATS unit tests..."
bats tests/bats/*.bats
echo "==> Running Pytest suite..."
pytest tests/pytest/ -v --tb=short
# ── Lint ─────────────────────────────────────────────────────────────
[group('test')]
lint:
#!/usr/bin/env bash
set -euo pipefail
SUDO_CMD=""
if [ "$(id -u)" -ne 0 ]; then
SUDO_CMD="sudo"
fi
echo "==> Linting {{image_name}}:{{image_tag}} with bootc container lint..."
$SUDO_CMD podman run --rm --privileged --pull=never \
"{{image_name}}:{{image_tag}}" \
bootc container lint