Skip to content

Commit 0e12e13

Browse files
committed
Add separate github workflow for azl3 raw image build
Signed-off-by: Teoh Suh Haw <suh.haw.teoh@intel.com>
1 parent c13bc7d commit 0e12e13

File tree

4 files changed

+362
-5
lines changed

4 files changed

+362
-5
lines changed

.github/workflows/PR_Tester.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,19 @@ jobs:
4343

4444
- name: Copy tester script
4545
run: |
46-
if [ ! -f validate.sh ]; then
47-
echo "validate.sh not found!"
46+
if [ ! -f scripts/validate.sh ]; then
47+
echo "scripts/validate.sh not found!"
4848
exit 1
4949
fi
50-
chmod +x validate.sh
50+
chmod +x scripts/validate.sh
5151
5252
- name: Run build-tester
5353
run: |
54-
echo "Starting validate.sh..."
54+
echo "Starting scripts/validate.sh..."
5555
# Ensure script has access to docker group for Earthly
5656
sudo usermod -aG docker $USER
5757
# Run the validation script
58-
./validate.sh
58+
./scripts/validate.sh
5959
echo "Build and tests completed."
6060
6161
# Runs only for PR-triggered events (not manual), so it's safe to leave in.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: Build AZL3 Raw Image
2+
on:
3+
workflow_dispatch: # Manual runs
4+
inputs:
5+
ref:
6+
description: "Branch or SHA to test (e.g. feature/x or a1b2c3)"
7+
required: false
8+
run_qemu_test:
9+
description: "Run QEMU boot test after build"
10+
required: false
11+
default: "false"
12+
type: choice
13+
options:
14+
- "true"
15+
- "false"
16+
push:
17+
branches:
18+
- main
19+
pull_request:
20+
branches:
21+
- main
22+
23+
permissions:
24+
contents: read
25+
26+
jobs:
27+
build-azl3-raw:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout PR code
31+
uses: actions/checkout@v4
32+
with:
33+
persist-credentials: false
34+
35+
- name: Set up Docker Buildx
36+
uses: docker/setup-buildx-action@v3
37+
38+
- name: Install Earthly
39+
uses: earthly/actions-setup@v1
40+
with:
41+
github-token: ${{ secrets.GITHUB_TOKEN }}
42+
version: "latest"
43+
44+
- name: Install system deps
45+
run: |
46+
sudo apt-get update
47+
sudo apt-get install -y qemu-system-x86 ovmf tree jq systemd-ukify mmdebstrap systemd-boot
48+
49+
- name: Set up Go
50+
uses: actions/setup-go@v5
51+
with:
52+
go-version: stable
53+
54+
- name: Prepare build script
55+
run: |
56+
if [ ! -f scripts/build_azl3_raw.sh ]; then
57+
echo "scripts/build_azl3_raw.sh not found!"
58+
exit 1
59+
fi
60+
chmod +x scripts/build_azl3_raw.sh
61+
62+
- name: Run AZL3 Raw Image Build
63+
env:
64+
RUN_QEMU_TEST: ${{ github.event.inputs.run_qemu_test }}
65+
run: |
66+
echo "Starting AZL3 raw image build..."
67+
# Ensure script has access to docker group for Earthly
68+
sudo usermod -aG docker $USER
69+
70+
# Prepare arguments with input validation
71+
ARGS=""
72+
case "${RUN_QEMU_TEST}" in
73+
"true")
74+
ARGS="--qemu-test"
75+
echo "QEMU boot test will be run after build"
76+
;;
77+
"false"|"")
78+
echo "QEMU boot test will be skipped"
79+
;;
80+
*)
81+
echo "Invalid input for run_qemu_test: ${RUN_QEMU_TEST}"
82+
exit 1
83+
;;
84+
esac
85+
86+
# Run the AZL3 raw image build script
87+
./scripts/build_azl3_raw.sh $ARGS
88+
echo "AZL3 raw image build completed."
89+
90+
- name: Notify on failure
91+
if: ${{ failure() && github.event_name == 'pull_request' }}
92+
env:
93+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
94+
REVIEWER_ID: srmungar
95+
run: |
96+
PR_AUTHOR=$(jq --raw-output 'try .pull_request.user.login // empty' "$GITHUB_EVENT_PATH")
97+
if [ -z "$PR_AUTHOR" ]; then
98+
echo "PR_AUTHOR not found in event payload. Skipping notification."
99+
exit 0
100+
fi
101+
COMMENT_BODY="Hey @$PR_AUTHOR and @$REVIEWER_ID — the AZL3 raw image build has failed. Please check the logs."
102+
curl -s -X POST \
103+
-H "Authorization: Bearer $GITHUB_TOKEN" \
104+
-H "Accept: application/vnd.github.v3+json" \
105+
--data "{\"body\": \"$COMMENT_BODY\"}" \
106+
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments"

scripts/build_azl3_raw.sh

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Parse command line arguments
5+
RUN_QEMU_TESTS=false
6+
WORKING_DIR="$(pwd)"
7+
8+
while [[ $# -gt 0 ]]; do
9+
case $1 in
10+
--qemu-test|--with-qemu)
11+
RUN_QEMU_TESTS=true
12+
shift
13+
;;
14+
--working-dir)
15+
WORKING_DIR="$2"
16+
shift 2
17+
;;
18+
-h|--help)
19+
echo "Usage: $0 [--qemu-test|--with-qemu] [--working-dir DIR]"
20+
echo " --qemu-test, --with-qemu Run QEMU boot tests after image build"
21+
echo " --working-dir DIR Set the working directory"
22+
echo " -h, --help Show this help message"
23+
exit 0
24+
;;
25+
*)
26+
echo "Unknown option $1"
27+
echo "Use -h or --help for usage information"
28+
exit 1
29+
;;
30+
esac
31+
done
32+
33+
# Centralized cleanup function for image files
34+
cleanup_image_files() {
35+
local cleanup_type="${1:-all}" # Options: all, raw, extracted
36+
37+
case "$cleanup_type" in
38+
"raw")
39+
echo "Cleaning up raw image files from build directories..."
40+
sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true
41+
sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true
42+
;;
43+
"extracted")
44+
echo "Cleaning up extracted image files in current directory..."
45+
rm -f *.raw 2>/dev/null || true
46+
;;
47+
"all"|*)
48+
echo "Cleaning up all temporary image files..."
49+
sudo rm -rf ./tmp/*/imagebuild/*/*.raw 2>/dev/null || true
50+
sudo rm -rf ./workspace/*/imagebuild/*/*.raw 2>/dev/null || true
51+
rm -f *.raw 2>/dev/null || true
52+
;;
53+
esac
54+
}
55+
56+
run_qemu_boot_test() {
57+
local IMAGE_PATTERN="$1"
58+
if [ -z "$IMAGE_PATTERN" ]; then
59+
echo "Error: Image pattern not provided to run_qemu_boot_test"
60+
return 1
61+
fi
62+
63+
BIOS="/usr/share/OVMF/OVMF_CODE_4M.fd"
64+
TIMEOUT=30
65+
SUCCESS_STRING="login:"
66+
LOGFILE="qemu_serial.log"
67+
68+
ORIGINAL_DIR=$(pwd)
69+
# Find compressed raw image path using pattern, handle permission issues
70+
FOUND_PATH=$(sudo -S find . -type f -name "*${IMAGE_PATTERN}*.raw.gz" 2>/dev/null | head -n 1)
71+
if [ -n "$FOUND_PATH" ]; then
72+
echo "Found compressed image at: $FOUND_PATH"
73+
IMAGE_DIR=$(dirname "$FOUND_PATH")
74+
75+
# Fix permissions for the image directory recursively to allow access
76+
IMAGE_ROOT_DIR=$(echo "$IMAGE_DIR" | cut -d'/' -f2) # Get the root directory (workspace or tmp)
77+
echo "Setting permissions recursively for ./$IMAGE_ROOT_DIR directory"
78+
sudo chmod -R 777 "./$IMAGE_ROOT_DIR"
79+
80+
cd "$IMAGE_DIR"
81+
82+
# Extract the .raw.gz file
83+
COMPRESSED_IMAGE=$(basename "$FOUND_PATH")
84+
RAW_IMAGE="${COMPRESSED_IMAGE%.gz}"
85+
echo "Extracting $COMPRESSED_IMAGE to $RAW_IMAGE..."
86+
87+
# Check available disk space before extraction
88+
AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}')
89+
COMPRESSED_SIZE=$(stat -c%s "$COMPRESSED_IMAGE" 2>/dev/null || echo "0")
90+
# Estimate uncompressed size (typically 4-6x larger for these images, being conservative)
91+
ESTIMATED_SIZE=$((COMPRESSED_SIZE * 6 / 1024))
92+
93+
echo "Disk space check: Available=${AVAILABLE_SPACE}KB, Estimated needed=${ESTIMATED_SIZE}KB"
94+
95+
# Always try aggressive cleanup first to ensure maximum space
96+
echo "Performing aggressive cleanup before extraction..."
97+
sudo rm -f *.raw 2>/dev/null || true
98+
sudo rm -f /tmp/*.raw 2>/dev/null || true
99+
sudo rm -rf ../../../cache/ 2>/dev/null || true
100+
sudo rm -rf ../../../tmp/*/imagebuild/*/*.raw 2>/dev/null || true
101+
sudo rm -rf ../../../workspace/*/imagebuild/*/*.raw 2>/dev/null || true
102+
103+
# Force filesystem sync and check space again
104+
sync
105+
AVAILABLE_SPACE=$(df . | tail -1 | awk '{print $4}')
106+
echo "Available space after cleanup: ${AVAILABLE_SPACE}KB"
107+
108+
if [ "$AVAILABLE_SPACE" -lt "$ESTIMATED_SIZE" ]; then
109+
echo "Warning: Still insufficient disk space after cleanup"
110+
echo "Attempting extraction to /tmp with streaming..."
111+
112+
# Check /tmp space
113+
TMP_AVAILABLE=$(df /tmp | tail -1 | awk '{print $4}')
114+
echo "/tmp available space: ${TMP_AVAILABLE}KB"
115+
116+
if [ "$TMP_AVAILABLE" -gt "$ESTIMATED_SIZE" ]; then
117+
TMP_RAW="/tmp/$RAW_IMAGE"
118+
echo "Extracting to /tmp first..."
119+
if gunzip -c "$COMPRESSED_IMAGE" > "$TMP_RAW"; then
120+
echo "Successfully extracted to /tmp, moving to final location..."
121+
if mv "$TMP_RAW" "$RAW_IMAGE"; then
122+
echo "Successfully moved extracted image to current directory"
123+
else
124+
echo "Failed to move from /tmp, will try to use /tmp location directly"
125+
ln -sf "$TMP_RAW" "$RAW_IMAGE" 2>/dev/null || cp "$TMP_RAW" "$RAW_IMAGE"
126+
fi
127+
else
128+
echo "Failed to extract to /tmp"
129+
rm -f "$TMP_RAW" 2>/dev/null || true
130+
return 1
131+
fi
132+
else
133+
echo "ERROR: Insufficient space in both current directory and /tmp"
134+
echo "Current: ${AVAILABLE_SPACE}KB, /tmp: ${TMP_AVAILABLE}KB, Needed: ${ESTIMATED_SIZE}KB"
135+
return 1
136+
fi
137+
else
138+
echo "Sufficient space available, extracting directly..."
139+
if ! gunzip -c "$COMPRESSED_IMAGE" > "$RAW_IMAGE"; then
140+
echo "Direct extraction failed, cleaning up partial file..."
141+
rm -f "$RAW_IMAGE" 2>/dev/null || true
142+
return 1
143+
fi
144+
fi
145+
146+
if [ ! -f "$RAW_IMAGE" ]; then
147+
echo "Failed to extract image!"
148+
# Clean up any partially extracted files
149+
sudo rm -f "$RAW_IMAGE" /tmp/"$RAW_IMAGE" 2>/dev/null || true
150+
cd "$ORIGINAL_DIR"
151+
return 1
152+
fi
153+
154+
IMAGE="$RAW_IMAGE"
155+
else
156+
echo "Compressed raw image file matching pattern '*${IMAGE_PATTERN}*.raw.gz' not found!"
157+
return 1
158+
fi
159+
160+
161+
echo "Booting image: $IMAGE "
162+
#create log file ,boot image into qemu , return the pass or fail after boot sucess
163+
sudo bash -c "
164+
LOGFILE=\"$LOGFILE\"
165+
SUCCESS_STRING=\"$SUCCESS_STRING\"
166+
IMAGE=\"$IMAGE\"
167+
RAW_IMAGE=\"$RAW_IMAGE\"
168+
ORIGINAL_DIR=\"$ORIGINAL_DIR\"
169+
170+
touch \"\$LOGFILE\" && chmod 666 \"\$LOGFILE\"
171+
nohup qemu-system-x86_64 \\
172+
-m 2048 \\
173+
-enable-kvm \\
174+
-cpu host \\
175+
-drive if=none,file=\"\$IMAGE\",format=raw,id=nvme0 \\
176+
-device nvme,drive=nvme0,serial=deadbeef \\
177+
-drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \\
178+
-drive if=pflash,format=raw,file=/usr/share/OVMF/OVMF_VARS_4M.fd \\
179+
-nographic \\
180+
-serial mon:stdio \\
181+
> \"\$LOGFILE\" 2>&1 &
182+
183+
qemu_pid=\$!
184+
echo \"QEMU launched as root with PID \$qemu_pid\"
185+
echo \"Current working dir: \$(pwd)\"
186+
187+
# Wait for SUCCESS_STRING or timeout
188+
timeout=30
189+
elapsed=0
190+
while ! grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\" && [ \$elapsed -lt \$timeout ]; do
191+
sleep 1
192+
elapsed=\$((elapsed + 1))
193+
done
194+
echo \"\$elapsed\"
195+
kill \$qemu_pid
196+
cat \"\$LOGFILE\"
197+
198+
if grep -q \"\$SUCCESS_STRING\" \"\$LOGFILE\"; then
199+
echo \"Boot success!\"
200+
result=0
201+
else
202+
echo \"Boot failed or timed out\"
203+
result=1
204+
fi
205+
206+
# Clean up extracted raw file
207+
if [ -f \"\$RAW_IMAGE\" ]; then
208+
echo \"Cleaning up extracted image file: \$RAW_IMAGE\"
209+
rm -f \"\$RAW_IMAGE\"
210+
fi
211+
212+
# Return to original directory
213+
cd \"\$ORIGINAL_DIR\"
214+
exit \$result
215+
"
216+
217+
# Get the exit code from the sudo bash command
218+
qemu_result=$?
219+
return $qemu_result
220+
}
221+
222+
build_azl3_raw_image() {
223+
echo "Building AZL3 raw Image. (using os-image-composer binary)"
224+
# Ensure we're in the working directory before starting builds
225+
echo "Ensuring we're in the working directory before starting builds..."
226+
cd "$WORKING_DIR"
227+
echo "Current working directory: $(pwd)"
228+
229+
output=$( sudo -S ./os-image-composer build image-templates/azl3-x86_64-minimal-raw.yml 2>&1)
230+
# Check for the success message in the output
231+
if echo "$output" | grep -q "image build completed successfully"; then
232+
echo "AZL3 raw Image build passed."
233+
if [ "$RUN_QEMU_TESTS" = true ]; then
234+
echo "Running QEMU boot test for AZL3 raw image..."
235+
if run_qemu_boot_test "azl3-x86_64-minimal"; then
236+
echo "QEMU boot test PASSED for AZL3 raw image"
237+
else
238+
echo "QEMU boot test FAILED for AZL3 raw image"
239+
exit 1
240+
fi
241+
# Clean up after QEMU test to free space
242+
cleanup_image_files raw
243+
fi
244+
else
245+
echo "AZL3 raw Image build failed."
246+
exit 1 # Exit with error if build fails
247+
fi
248+
}
249+
250+
# Run the main function
251+
build_azl3_raw_image
File renamed without changes.

0 commit comments

Comments
 (0)