Skip to content

Commit 97a9e96

Browse files
committed
feat: add github actions workflow for ISO release
1 parent e9793e2 commit 97a9e96

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

.github/workflows/build-iso.yml

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
name: Build CVH Linux ISO
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: "Release version (e.g., v2026.03.31). Auto-generated if empty."
8+
required: false
9+
default: ""
10+
push:
11+
tags:
12+
- "v*"
13+
14+
permissions:
15+
contents: write
16+
17+
concurrency:
18+
group: iso-build
19+
cancel-in-progress: false
20+
21+
jobs:
22+
build-and-release:
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 120
25+
26+
steps:
27+
- name: Free disk space
28+
run: |
29+
sudo rm -rf /usr/share/dotnet
30+
sudo rm -rf /usr/local/lib/android
31+
sudo rm -rf /opt/ghc
32+
sudo rm -rf /opt/hostedtoolcache
33+
sudo docker image prune --all --force
34+
df -h /
35+
36+
- name: Checkout repository
37+
uses: actions/checkout@v4
38+
with:
39+
fetch-depth: 0
40+
41+
- name: Determine version
42+
id: version
43+
run: |
44+
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ -n "${{ github.event.inputs.version }}" ]; then
45+
VERSION="${{ github.event.inputs.version }}"
46+
elif [ "${{ github.event_name }}" = "push" ]; then
47+
VERSION="${GITHUB_REF#refs/tags/}"
48+
else
49+
VERSION="v$(date +%Y.%m.%d)"
50+
fi
51+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
52+
echo "Version: $VERSION"
53+
54+
- name: Build ISO in Arch Linux container
55+
run: |
56+
docker run --rm --privileged \
57+
-v "${{ github.workspace }}:/build" \
58+
-e TERM=xterm \
59+
archlinux:latest \
60+
bash -c '
61+
set -euo pipefail
62+
63+
# ── 1. System setup ──────────────────────────────────────
64+
echo "::group::Initialize pacman"
65+
pacman-key --init
66+
pacman-key --populate archlinux
67+
pacman -Syu --noconfirm
68+
echo "::endgroup::"
69+
70+
# ── 2. Install build dependencies ────────────────────────
71+
echo "::group::Install dependencies"
72+
pacman -S --noconfirm --needed \
73+
archiso \
74+
squashfs-tools \
75+
libisoburn \
76+
grub \
77+
base-devel \
78+
git \
79+
rust \
80+
lua \
81+
wayland \
82+
wayland-protocols
83+
echo "::endgroup::"
84+
85+
# ── 3. Create non-root builder user ──────────────────────
86+
# makepkg refuses to run as root; mkarchiso requires root.
87+
# We run package builds as "builder" and ISO build as root.
88+
useradd -m builder
89+
echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
90+
chown -R builder:builder /build/src /build/pkgbuild /build/repo /build/configs
91+
92+
# ── 4. Reorder mirrors for CI speed ──────────────────────
93+
# The ISO pacman.conf has Israeli mirrors first, which are slow
94+
# from GitHub runners. Prepend the geo mirror for faster downloads.
95+
# (The duplicate geo entry lower in the list is harmless.)
96+
sed -i "/^\[core\]$/a Server = https://geo.mirror.pkgbuild.com/\$repo/os/\$arch" /build/iso/pacman.conf
97+
sed -i "/^\[extra\]$/a Server = https://geo.mirror.pkgbuild.com/\$repo/os/\$arch" /build/iso/pacman.conf
98+
99+
# ── 5. Build packages (as non-root builder) ──────────────
100+
echo "::group::Build packages"
101+
cd /build
102+
runuser -u builder -- bash scripts/build-packages.sh
103+
echo "::endgroup::"
104+
105+
# ── 6. Build ISO (as root via build-iso.sh -n) ───────────
106+
echo "::group::Build ISO"
107+
cd /build
108+
bash scripts/build-iso.sh -n
109+
echo "::endgroup::"
110+
'
111+
112+
- name: Generate checksum and identify ISO
113+
id: iso
114+
run: |
115+
ISO_FILE=$(ls ${{ github.workspace }}/out/*.iso | head -1)
116+
ISO_NAME=$(basename "$ISO_FILE")
117+
sha256sum "$ISO_FILE" > "${ISO_FILE}.sha256"
118+
SHA256=$(cut -d' ' -f1 < "${ISO_FILE}.sha256")
119+
ISO_SIZE=$(stat --format=%s "$ISO_FILE")
120+
121+
echo "file=$ISO_FILE" >> "$GITHUB_OUTPUT"
122+
echo "name=$ISO_NAME" >> "$GITHUB_OUTPUT"
123+
echo "sha256=$SHA256" >> "$GITHUB_OUTPUT"
124+
echo "size=$ISO_SIZE" >> "$GITHUB_OUTPUT"
125+
126+
echo "ISO: $ISO_NAME"
127+
echo "SHA256: $SHA256"
128+
echo "Size: $(du -h "$ISO_FILE" | cut -f1)"
129+
130+
- name: Compress ISO if over 2GB
131+
id: compress
132+
run: |
133+
ISO_FILE="${{ steps.iso.outputs.file }}"
134+
ISO_SIZE="${{ steps.iso.outputs.size }}"
135+
LIMIT=$((2 * 1024 * 1024 * 1024)) # 2 GiB
136+
137+
if [ "$ISO_SIZE" -gt "$LIMIT" ]; then
138+
echo "ISO exceeds 2GB ($ISO_SIZE bytes), compressing with zstd..."
139+
zstd -T0 -10 "$ISO_FILE" -o "${ISO_FILE}.zst"
140+
sha256sum "${ISO_FILE}.zst" > "${ISO_FILE}.zst.sha256"
141+
ZST_SHA256=$(cut -d' ' -f1 < "${ISO_FILE}.zst.sha256")
142+
143+
echo "compressed=true" >> "$GITHUB_OUTPUT"
144+
echo "zst_file=${ISO_FILE}.zst" >> "$GITHUB_OUTPUT"
145+
echo "zst_name=$(basename "${ISO_FILE}.zst")" >> "$GITHUB_OUTPUT"
146+
echo "zst_sha256=$ZST_SHA256" >> "$GITHUB_OUTPUT"
147+
echo "Compressed: $(du -h "${ISO_FILE}.zst" | cut -f1)"
148+
else
149+
echo "compressed=false" >> "$GITHUB_OUTPUT"
150+
echo "ISO is under 2GB, no compression needed."
151+
fi
152+
153+
- name: Create GitHub Release (direct ISO)
154+
if: steps.compress.outputs.compressed == 'false'
155+
uses: softprops/action-gh-release@v2
156+
with:
157+
tag_name: ${{ steps.version.outputs.version }}
158+
name: CVH Linux ${{ steps.version.outputs.version }}
159+
body: |
160+
## CVH Linux ${{ steps.version.outputs.version }}
161+
162+
### Download
163+
| File | SHA256 |
164+
|------|--------|
165+
| `${{ steps.iso.outputs.name }}` | `${{ steps.iso.outputs.sha256 }}` |
166+
167+
### Verify
168+
```bash
169+
sha256sum -c ${{ steps.iso.outputs.name }}.sha256
170+
```
171+
172+
### Write to USB
173+
```bash
174+
sudo dd if=${{ steps.iso.outputs.name }} of=/dev/sdX bs=4M status=progress oflag=sync
175+
```
176+
files: |
177+
${{ steps.iso.outputs.file }}
178+
${{ steps.iso.outputs.file }}.sha256
179+
draft: false
180+
prerelease: false
181+
182+
- name: Create GitHub Release (compressed ISO)
183+
if: steps.compress.outputs.compressed == 'true'
184+
uses: softprops/action-gh-release@v2
185+
with:
186+
tag_name: ${{ steps.version.outputs.version }}
187+
name: CVH Linux ${{ steps.version.outputs.version }}
188+
body: |
189+
## CVH Linux ${{ steps.version.outputs.version }}
190+
191+
> The ISO was compressed with `zstd` because it exceeds GitHub's 2GB asset limit.
192+
> Decompress after download: `zstd -d ${{ steps.compress.outputs.zst_name }}`
193+
194+
### Download
195+
| File | SHA256 |
196+
|------|--------|
197+
| `${{ steps.compress.outputs.zst_name }}` | `${{ steps.compress.outputs.zst_sha256 }}` |
198+
199+
### Verify & decompress
200+
```bash
201+
sha256sum -c ${{ steps.compress.outputs.zst_name }}.sha256
202+
zstd -d ${{ steps.compress.outputs.zst_name }}
203+
```
204+
205+
### Uncompressed ISO checksum
206+
| File | SHA256 |
207+
|------|--------|
208+
| `${{ steps.iso.outputs.name }}` | `${{ steps.iso.outputs.sha256 }}` |
209+
210+
### Write to USB
211+
```bash
212+
zstd -d ${{ steps.compress.outputs.zst_name }}
213+
sudo dd if=${{ steps.iso.outputs.name }} of=/dev/sdX bs=4M status=progress oflag=sync
214+
```
215+
files: |
216+
${{ steps.compress.outputs.zst_file }}
217+
${{ steps.compress.outputs.zst_file }}.sha256
218+
draft: false
219+
prerelease: false

0 commit comments

Comments
 (0)