Skip to content

Commit 2feaa06

Browse files
committed
ci(build-image-template): emit per-build rpi-imager.json when opted in
Wires the existing `enable-rpi-imager-snippet` input (previously declared but unused) to actually emit a single-image rpi-imager.json next to the built .img.xz / .zip, attached to the same GitHub release. The snippet captures everything Pi Imager needs to flash the build without going through the aggregated rpi-imager-json release: image URL, decompressed sha256, compressed download size, decompressed extract size, icon, name, description, plus the standard Pi-device discovery list (Pi 5 / 4 / 3 / Zero 2 W). Off by default. Existing builds are unaffected.
1 parent 138a088 commit 2feaa06

1 file changed

Lines changed: 78 additions & 5 deletions

File tree

.github/workflows/build-image-template.yml

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,29 +121,98 @@ jobs:
121121
id: sha256
122122
run: |
123123
IMAGE_PATH="${{ steps.build.outputs.image-path }}"
124-
124+
125125
# Determine if image-path is a file
126126
if [ -f "$IMAGE_PATH" ]; then
127127
# Calculate SHA256 hash and extract only the hash value
128128
SHA256_HASH=$(sha256sum "$IMAGE_PATH" | awk '{print $1}')
129-
129+
130130
# Get file size in bytes
131131
FILE_SIZE=$(stat -c%s "$IMAGE_PATH")
132-
132+
133133
# Write hash to sha256 file
134134
echo "${SHA256_HASH} $(basename "$IMAGE_PATH")" > "${IMAGE_PATH}.sha256"
135-
135+
136136
# Set as GitHub Action outputs
137137
echo "sha256_hash=${SHA256_HASH}" >> $GITHUB_OUTPUT
138138
echo "file_size=${FILE_SIZE}" >> $GITHUB_OUTPUT
139-
139+
echo "image_path=${IMAGE_PATH}" >> $GITHUB_OUTPUT
140+
echo "image_basename=$(basename "$IMAGE_PATH")" >> $GITHUB_OUTPUT
141+
140142
echo "SHA256 checksum generated for: $IMAGE_PATH"
141143
echo "SHA256 hash: $SHA256_HASH"
142144
echo "File size: $FILE_SIZE bytes"
143145
else
144146
echo "::warning::Image path not found: $IMAGE_PATH"
145147
fi
146148
149+
# Generate a single-image rpi-imager.json so the user can load this
150+
# specific build directly via "Use custom image" / repo URL in Pi Imager.
151+
# Only runs when the build job opts in via enable-rpi-imager-snippet.
152+
- name: Generate single-image rpi-imager.json
153+
if: inputs.enable-rpi-imager-snippet && steps.sha256.outputs.image_path != ''
154+
id: imager-json
155+
run: |
156+
IMAGE_PATH="${{ steps.sha256.outputs.image_path }}"
157+
BASENAME="${{ steps.sha256.outputs.image_basename }}"
158+
DOWNLOAD_SIZE="${{ steps.sha256.outputs.file_size }}"
159+
160+
REF_NAME="${{ github.ref_name }}"
161+
REF_ENCODED="${REF_NAME//\//%2F}"
162+
IMAGE_URL="https://github.com/${{ github.repository }}/releases/download/${REF_ENCODED}/${BASENAME}"
163+
164+
# Pi Imager validates the decompressed image, not the .xz wrapper,
165+
# so the published sha256 must be of the underlying .img.
166+
if [[ "$BASENAME" == *.xz ]]; then
167+
EXTRACT_SHA256=$(xzcat "$IMAGE_PATH" | sha256sum | awk '{print $1}')
168+
EXTRACT_SIZE=$(xz --list --robot "$IMAGE_PATH" | awk '/^totals/ {print $5}')
169+
elif [[ "$BASENAME" == *.zip ]]; then
170+
EXTRACT_SHA256=$(unzip -p "$IMAGE_PATH" | sha256sum | awk '{print $1}')
171+
EXTRACT_SIZE=$(unzip -l "$IMAGE_PATH" | awk '/[0-9]+ +[0-9-]+ +[0-9:]+ +.+\.img$/ {print $1}' | head -1)
172+
else
173+
EXTRACT_SHA256="$(sha256sum "$IMAGE_PATH" | awk '{print $1}')"
174+
EXTRACT_SIZE="$DOWNLOAD_SIZE"
175+
fi
176+
177+
OS_NAME="${{ inputs.image-name }}"
178+
# raw.githubusercontent.com handles slashes in refs natively, so
179+
# we keep REF_NAME un-encoded here even though the releases URL
180+
# above needs the %2F form.
181+
ICON_URL="https://raw.githubusercontent.com/${{ github.repository }}/${REF_NAME}/docs/respeaker_2michats.webp"
182+
183+
cat > rpi-imager.json <<JSON
184+
{
185+
"imager": {
186+
"latest_version": "${REF_NAME}",
187+
"url": "https://www.raspberrypi.com/software/",
188+
"devices": [
189+
{"name": "Raspberry Pi 5", "tags": ["pi5-64bit", "pi5-32bit"], "default": true, "icon": "https://downloads.raspberrypi.com/imager/icons/RPi_5.png", "description": "Raspberry Pi 5, 500 / 500+, and Compute Module 5", "matching_type": "exclusive", "capabilities": []},
190+
{"name": "Raspberry Pi 4", "tags": ["pi4-64bit", "pi4-32bit"], "icon": "https://downloads.raspberrypi.com/imager/icons/RPi_4.png", "description": "Raspberry Pi 4 Model B, 400, and Compute Module 4 / 4S", "matching_type": "inclusive", "capabilities": []},
191+
{"name": "Raspberry Pi 3", "tags": ["pi3-64bit", "pi3-32bit"], "icon": "https://downloads.raspberrypi.com/imager/icons/RPi_3.png", "description": "Raspberry Pi 3 Model A+ / B / B+ and Compute Module 3 / 3+", "matching_type": "inclusive", "capabilities": []},
192+
{"name": "Raspberry Pi Zero 2 W", "tags": ["pi3-64bit", "pi3-32bit"], "icon": "https://downloads.raspberrypi.com/imager/icons/RPi_Zero_2_W.png", "description": "Raspberry Pi Zero 2 W", "matching_type": "inclusive", "capabilities": []}
193+
]
194+
},
195+
"os_list": [
196+
{
197+
"name": "${OS_NAME} (${REF_NAME})",
198+
"description": "PiCompose image: 2-Mic HAT v2 + Linux Voice Assistant from feat/peripheral-led-light-entity (Light entity + Rainbow effect, ReSpeaker 2-Mic peripheral). Built ${{ github.sha }} on branch ${REF_NAME}.",
199+
"icon": "${ICON_URL}",
200+
"url": "${IMAGE_URL}",
201+
"init_format": "systemd",
202+
"image_download_size": ${DOWNLOAD_SIZE},
203+
"extract_size": ${EXTRACT_SIZE},
204+
"extract_sha256": "${EXTRACT_SHA256}",
205+
"devices": ["pi5-64bit", "pi4-64bit", "pi3-64bit"],
206+
"capabilities": ["ssh", "wifi", "hostname", "locale"]
207+
}
208+
]
209+
}
210+
JSON
211+
212+
echo "rpi-imager.json:"
213+
cat rpi-imager.json
214+
echo "imager_json_path=$(pwd)/rpi-imager.json" >> $GITHUB_OUTPUT
215+
147216
# Build the image URL for releases
148217
- name: Build image URL
149218
id: image-url
@@ -175,9 +244,11 @@ jobs:
175244
generate_release_notes: true
176245
prerelease: false
177246
draft: false
247+
fail_on_unmatched_files: false
178248
files: |
179249
${{ steps.build.outputs.image-path }}
180250
${{ steps.build.outputs.image-path }}.sha256
251+
rpi-imager.json
181252
env:
182253
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
183254

@@ -190,9 +261,11 @@ jobs:
190261
generate_release_notes: true
191262
prerelease: true
192263
draft: false
264+
fail_on_unmatched_files: false
193265
files: |
194266
${{ steps.build.outputs.image-path }}
195267
${{ steps.build.outputs.image-path }}.sha256
268+
rpi-imager.json
196269
env:
197270
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
198271

0 commit comments

Comments
 (0)