mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 12:37:20 +01:00
build: Update workflow (#2012)
This commit is contained in:
+293
-28
@@ -19,10 +19,10 @@ on:
|
|||||||
default: ubuntu-24.04
|
default: ubuntu-24.04
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
image:
|
branch:
|
||||||
description: Container image to test
|
description: Repository branch to build
|
||||||
required: false
|
required: false
|
||||||
default: ghcr.io/dockur/windows:latest
|
default: dev
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
callback:
|
callback:
|
||||||
@@ -31,12 +31,48 @@ on:
|
|||||||
default: powershell
|
default: powershell
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
machine:
|
||||||
|
description: QEMU machine type exposed to Windows
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
type: string
|
||||||
|
|
||||||
cpu:
|
cpu:
|
||||||
description: CPU model exposed to Windows
|
description: CPU model exposed to Windows
|
||||||
required: false
|
required: false
|
||||||
default: host
|
default: ""
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
cpu_flags:
|
||||||
|
description: Additional CPU flags exposed to Windows
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
type: string
|
||||||
|
|
||||||
|
disk_type:
|
||||||
|
description: Disk controller type exposed to Windows
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
type: string
|
||||||
|
|
||||||
|
network:
|
||||||
|
description: Network backend exposed to Windows
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
type: string
|
||||||
|
|
||||||
|
adapter:
|
||||||
|
description: Network adapter exposed to Windows
|
||||||
|
required: false
|
||||||
|
default: ""
|
||||||
|
type: string
|
||||||
|
|
||||||
|
kill_on_failure:
|
||||||
|
description: Stop the workflow when an installation failure is detected
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
|
||||||
expected_caption:
|
expected_caption:
|
||||||
description: Text expected in the Windows caption
|
description: Text expected in the Windows caption
|
||||||
required: true
|
required: true
|
||||||
@@ -69,9 +105,45 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
CONTAINER: windows-test
|
CONTAINER: windows-test
|
||||||
IMAGE: ${{ inputs.image }}
|
IMAGE: windows-validation:local
|
||||||
|
TUNNEL: windows-test-tunnel
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Resolve branch
|
||||||
|
id: branch
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
REQUESTED_BRANCH: ${{ inputs.branch }}
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
authorization="$(
|
||||||
|
printf 'x-access-token:%s' "$GITHUB_TOKEN" |
|
||||||
|
base64 -w 0
|
||||||
|
)"
|
||||||
|
|
||||||
|
if git \
|
||||||
|
-c "http.extraheader=Authorization: basic $authorization" \
|
||||||
|
ls-remote \
|
||||||
|
--exit-code \
|
||||||
|
--heads \
|
||||||
|
"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git" \
|
||||||
|
"refs/heads/$REQUESTED_BRANCH" > /dev/null 2>&1; then
|
||||||
|
|
||||||
|
branch="$REQUESTED_BRANCH"
|
||||||
|
else
|
||||||
|
branch="master"
|
||||||
|
echo "Branch '$REQUESTED_BRANCH' does not exist; using '$branch'."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "branch=$branch" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Checkout branch
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
ref: ${{ steps.branch.outputs.branch }}
|
||||||
|
|
||||||
- name: Check KVM
|
- name: Check KVM
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -166,6 +238,61 @@ jobs:
|
|||||||
goto sync
|
goto sync
|
||||||
BATCH
|
BATCH
|
||||||
|
|
||||||
|
cat > "$RUNNER_TEMP/oem/shutdown.vbs" <<'VBSCRIPT'
|
||||||
|
On Error Resume Next
|
||||||
|
|
||||||
|
Dim service
|
||||||
|
Dim systems
|
||||||
|
Dim system
|
||||||
|
|
||||||
|
Set service = GetObject("winmgmts:{impersonationLevel=impersonate,(Shutdown)}!\\.\root\cimv2")
|
||||||
|
Set systems = service.ExecQuery("SELECT * FROM Win32_OperatingSystem")
|
||||||
|
|
||||||
|
For Each system In systems
|
||||||
|
system.Win32Shutdown 5
|
||||||
|
Next
|
||||||
|
VBSCRIPT
|
||||||
|
|
||||||
|
cat > "$RUNNER_TEMP/oem/watchdog.vbs" <<'VBSCRIPT'
|
||||||
|
Option Explicit
|
||||||
|
|
||||||
|
Const ForAppending = 8
|
||||||
|
|
||||||
|
Dim filesystem
|
||||||
|
Dim file
|
||||||
|
Dim shell
|
||||||
|
Dim service
|
||||||
|
Dim systems
|
||||||
|
Dim system
|
||||||
|
|
||||||
|
WScript.Sleep 180000
|
||||||
|
|
||||||
|
Set filesystem = CreateObject("Scripting.FileSystemObject")
|
||||||
|
|
||||||
|
If filesystem.FileExists("C:\OEM\install.done") Then
|
||||||
|
WScript.Quit 0
|
||||||
|
End If
|
||||||
|
|
||||||
|
On Error Resume Next
|
||||||
|
|
||||||
|
Set file = filesystem.OpenTextFile("C:\OEM\install.log", ForAppending, True)
|
||||||
|
file.WriteLine Now & " - Callback failed for 3 minutes."
|
||||||
|
file.Close
|
||||||
|
|
||||||
|
Set file = filesystem.CreateTextFile("C:\OEM\install.done", True)
|
||||||
|
file.Close
|
||||||
|
|
||||||
|
Set shell = CreateObject("WScript.Shell")
|
||||||
|
shell.Run "shutdown.exe -s -f -t 0", 0, False
|
||||||
|
|
||||||
|
Set service = GetObject("winmgmts:{impersonationLevel=impersonate,(Shutdown)}!\\.\root\cimv2")
|
||||||
|
Set systems = service.ExecQuery("SELECT * FROM Win32_OperatingSystem")
|
||||||
|
|
||||||
|
For Each system In systems
|
||||||
|
system.Win32Shutdown 5
|
||||||
|
Next
|
||||||
|
VBSCRIPT
|
||||||
|
|
||||||
case "$CALLBACK" in
|
case "$CALLBACK" in
|
||||||
powershell)
|
powershell)
|
||||||
cat > "$RUNNER_TEMP/oem/ready.ps1" <<'POWERSHELL'
|
cat > "$RUNNER_TEMP/oem/ready.ps1" <<'POWERSHELL'
|
||||||
@@ -244,12 +371,22 @@ jobs:
|
|||||||
@echo off
|
@echo off
|
||||||
del /Q C:\OEM\install.done 2>nul
|
del /Q C:\OEM\install.done 2>nul
|
||||||
start "" /B cmd.exe /C C:\OEM\sync-log.bat
|
start "" /B cmd.exe /C C:\OEM\sync-log.bat
|
||||||
|
start "" /B cscript.exe //B //NoLogo C:\OEM\watchdog.vbs
|
||||||
|
|
||||||
powershell.exe -NoProfile -ExecutionPolicy Bypass ^
|
powershell.exe -NoProfile -ExecutionPolicy Bypass ^
|
||||||
-File C:\OEM\ready.ps1 ^
|
-File C:\OEM\ready.ps1 ^
|
||||||
-Token "$token"
|
-Token "$token"
|
||||||
|
|
||||||
set "result=%errorlevel%"
|
set "result=%errorlevel%"
|
||||||
|
|
||||||
|
if not "%result%"=="0" (
|
||||||
|
echo %date% %time% - Callback failed.>>C:\OEM\install.log
|
||||||
|
type nul > C:\OEM\install.done
|
||||||
|
shutdown.exe -s -f -t 0 >nul 2>&1
|
||||||
|
if errorlevel 1 cscript.exe //B //NoLogo C:\OEM\shutdown.vbs
|
||||||
|
exit /B %result%
|
||||||
|
)
|
||||||
|
|
||||||
type nul > C:\OEM\install.done
|
type nul > C:\OEM\install.done
|
||||||
call C:\OEM\sync-log.bat once
|
call C:\OEM\sync-log.bat once
|
||||||
exit /B %result%
|
exit /B %result%
|
||||||
@@ -443,10 +580,20 @@ jobs:
|
|||||||
@echo off
|
@echo off
|
||||||
del /Q C:\OEM\install.done 2>nul
|
del /Q C:\OEM\install.done 2>nul
|
||||||
start "" /B cmd.exe /C C:\OEM\sync-log.bat
|
start "" /B cmd.exe /C C:\OEM\sync-log.bat
|
||||||
|
start "" /B cscript.exe //B //NoLogo C:\OEM\watchdog.vbs
|
||||||
|
|
||||||
cscript.exe //B //NoLogo C:\OEM\ready.vbs "$token"
|
cscript.exe //B //NoLogo C:\OEM\ready.vbs "$token"
|
||||||
|
|
||||||
set "result=%errorlevel%"
|
set "result=%errorlevel%"
|
||||||
|
|
||||||
|
if not "%result%"=="0" (
|
||||||
|
echo %date% %time% - Callback failed.>>C:\OEM\install.log
|
||||||
|
type nul > C:\OEM\install.done
|
||||||
|
shutdown.exe -s -f -t 0 >nul 2>&1
|
||||||
|
if errorlevel 1 cscript.exe //B //NoLogo C:\OEM\shutdown.vbs
|
||||||
|
exit /B %result%
|
||||||
|
)
|
||||||
|
|
||||||
type nul > C:\OEM\install.done
|
type nul > C:\OEM\install.done
|
||||||
call C:\OEM\sync-log.bat once
|
call C:\OEM\sync-log.bat once
|
||||||
exit /B %result%
|
exit /B %result%
|
||||||
@@ -456,27 +603,44 @@ jobs:
|
|||||||
|
|
||||||
echo "token=$token" >> "$GITHUB_OUTPUT"
|
echo "token=$token" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Pull image
|
- name: Build image
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
docker pull "$IMAGE"
|
echo "Building branch: ${{ steps.branch.outputs.branch }}"
|
||||||
|
echo "Commit: $(git rev-parse HEAD)"
|
||||||
|
|
||||||
|
for attempt in 1 2 3; do
|
||||||
|
if docker build \
|
||||||
|
--tag "$IMAGE" \
|
||||||
|
. >/dev/null 2>/dev/null; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( attempt == 3 )); then
|
||||||
|
echo "Image build failed after $attempt attempts."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
delay=$((attempt * 15))
|
||||||
|
echo "Image build failed, retrying in $delay seconds..."
|
||||||
|
sleep "$delay"
|
||||||
|
done
|
||||||
|
|
||||||
docker image inspect "$IMAGE" \
|
docker image inspect "$IMAGE" \
|
||||||
--format 'Digest: {{index .RepoDigests 0}}'
|
--format 'Image ID: {{.Id}}'
|
||||||
|
|
||||||
- name: Install and validate Windows
|
- name: Start Windows container
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
|
ADAPTER: ${{ inputs.adapter }}
|
||||||
CPU: ${{ inputs.cpu }}
|
CPU: ${{ inputs.cpu }}
|
||||||
EXPECTED_TOKEN: ${{ steps.test.outputs.token }}
|
CPU_FLAGS: ${{ inputs.cpu_flags }}
|
||||||
EXPECTED_CAPTION: ${{ inputs.expected_caption }}
|
DISK_TYPE: ${{ inputs.disk_type }}
|
||||||
EXPECTED_EDITION: ${{ inputs.expected_edition }}
|
MACHINE: ${{ inputs.machine }}
|
||||||
EXPECTED_PLATFORM: ${{ inputs.platform }}
|
NETWORK: ${{ inputs.network }}
|
||||||
MINIMUM_BUILD: ${{ inputs.minimum_build }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
DISPLAY_NAME: ${{ inputs.name }}
|
|
||||||
run: |
|
run: |
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
@@ -486,17 +650,86 @@ jobs:
|
|||||||
--device /dev/net/tun \
|
--device /dev/net/tun \
|
||||||
--cap-add NET_ADMIN \
|
--cap-add NET_ADMIN \
|
||||||
--stop-timeout 120 \
|
--stop-timeout 120 \
|
||||||
|
--env "MACHINE=$MACHINE" \
|
||||||
--env "VERSION=$VERSION" \
|
--env "VERSION=$VERSION" \
|
||||||
--env "RAM_SIZE=half" \
|
--env "RAM_SIZE=half" \
|
||||||
--env "CPU_CORES=half" \
|
--env "CPU_CORES=half" \
|
||||||
--env "CPU_MODEL=$CPU" \
|
|
||||||
--env "LOG=Y" \
|
|
||||||
--env "DISK_SIZE=64G" \
|
--env "DISK_SIZE=64G" \
|
||||||
|
--env "CPU_MODEL=$CPU" \
|
||||||
|
--env "CPU_FLAGS=$CPU_FLAGS" \
|
||||||
|
--env "DISK_TYPE=$DISK_TYPE" \
|
||||||
|
--env "NETWORK=$NETWORK" \
|
||||||
|
--env "ADAPTER=$ADAPTER" \
|
||||||
|
--env "LOG=Y" \
|
||||||
|
--env "DEBUG=Y" \
|
||||||
|
--env "LOSSY=Y" \
|
||||||
--volume "$RUNNER_TEMP/data:/shared" \
|
--volume "$RUNNER_TEMP/data:/shared" \
|
||||||
--volume "$RUNNER_TEMP/oem:/oem:ro" \
|
--volume "$RUNNER_TEMP/oem:/oem:ro" \
|
||||||
--volume "$RUNNER_TEMP/storage:/storage" \
|
--volume "$RUNNER_TEMP/storage:/storage" \
|
||||||
"$IMAGE"
|
"$IMAGE"
|
||||||
|
|
||||||
|
- name: Start noVNC tunnel
|
||||||
|
if: ${{ !inputs.kill_on_failure }}
|
||||||
|
id: tunnel
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
if docker run --detach \
|
||||||
|
--name "$TUNNEL" \
|
||||||
|
--network "container:$CONTAINER" \
|
||||||
|
cloudflare/cloudflared:latest \
|
||||||
|
tunnel \
|
||||||
|
--no-autoupdate \
|
||||||
|
--url http://127.0.0.1:8006 > /dev/null 2>/dev/null; then
|
||||||
|
novnc_url=""
|
||||||
|
|
||||||
|
for _ in {1..30}; do
|
||||||
|
novnc_url="$(
|
||||||
|
docker logs "$TUNNEL" 2>&1 |
|
||||||
|
grep -Eo 'https://[-a-z0-9]+\.trycloudflare\.com' |
|
||||||
|
tail -n 1 || true
|
||||||
|
)"
|
||||||
|
|
||||||
|
[ -n "$novnc_url" ] && break
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$novnc_url" ]; then
|
||||||
|
echo
|
||||||
|
echo "::notice title=noVNC viewer::$novnc_url"
|
||||||
|
echo "noVNC viewer: $novnc_url"
|
||||||
|
echo "Warning: this temporary URL is publicly accessible."
|
||||||
|
echo "url=$novnc_url" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "### noVNC viewer"
|
||||||
|
echo
|
||||||
|
echo "[$novnc_url]($novnc_url)"
|
||||||
|
echo
|
||||||
|
echo "> This temporary URL is publicly accessible while the job is running."
|
||||||
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
else
|
||||||
|
echo "::warning::Failed to obtain a noVNC tunnel URL."
|
||||||
|
docker logs "$TUNNEL" 2>&1 || true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "::warning::Failed to start the noVNC tunnel."
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install and validate Windows
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
KILL_ON_FAILURE: ${{ inputs.kill_on_failure }}
|
||||||
|
EXPECTED_TOKEN: ${{ steps.test.outputs.token }}
|
||||||
|
EXPECTED_CAPTION: ${{ inputs.expected_caption }}
|
||||||
|
EXPECTED_EDITION: ${{ inputs.expected_edition }}
|
||||||
|
EXPECTED_PLATFORM: ${{ inputs.platform }}
|
||||||
|
MINIMUM_BUILD: ${{ inputs.minimum_build }}
|
||||||
|
DISPLAY_NAME: ${{ inputs.name }}
|
||||||
|
run: |
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Container log:"
|
echo "Container log:"
|
||||||
echo "------------------------------------------------------------"
|
echo "------------------------------------------------------------"
|
||||||
@@ -541,10 +774,27 @@ jobs:
|
|||||||
|
|
||||||
trap stop_logs EXIT
|
trap stop_logs EXIT
|
||||||
|
|
||||||
|
failure_checks_disabled=0
|
||||||
|
|
||||||
|
handle_failure() {
|
||||||
|
local message="$1"
|
||||||
|
|
||||||
|
if [[ "$KILL_ON_FAILURE" == "true" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Automatic termination is disabled by kill_on_failure."
|
||||||
|
echo "The container and noVNC tunnel will remain available."
|
||||||
|
echo "::warning title=Failure detected::$message"
|
||||||
|
failure_checks_disabled=1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
deadline=$((SECONDS + 9000))
|
deadline=$((SECONDS + 9000))
|
||||||
reboot_timeout=1800
|
reboot_timeout=1800
|
||||||
minimum_reboots=1
|
minimum_reboots=1
|
||||||
boot_loop_limit=5
|
boot_loop_limit=10
|
||||||
first_bios_start=-1
|
first_bios_start=-1
|
||||||
|
|
||||||
while (( SECONDS < deadline )); do
|
while (( SECONDS < deadline )); do
|
||||||
@@ -564,22 +814,30 @@ jobs:
|
|||||||
|
|
||||||
container_log="$(docker logs "$CONTAINER" 2>&1 || true)"
|
container_log="$(docker logs "$CONTAINER" 2>&1 || true)"
|
||||||
|
|
||||||
if grep -Eqi \
|
if (( failure_checks_disabled == 0 )) &&
|
||||||
'KVM internal error|KVM: entry failed|hardware error 0x[0-9a-f]+|Triple fault' \
|
grep -Eqi \
|
||||||
<<< "$container_log"; then
|
'KVM internal error|KVM: entry failed|hardware error 0x[0-9a-f]+|Triple fault' \
|
||||||
|
<<< "$container_log"; then
|
||||||
echo
|
echo
|
||||||
echo "------------------------------------------------------------"
|
echo "------------------------------------------------------------"
|
||||||
echo "Detected a fatal QEMU or KVM error."
|
echo "Detected a fatal QEMU or KVM error."
|
||||||
exit 1
|
|
||||||
|
if ! handle_failure "Detected a fatal QEMU or KVM error."; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep -Eqi \
|
if (( failure_checks_disabled == 0 )) &&
|
||||||
'CDBOOT: Cannot boot from CD.*Code: 5' \
|
grep -Eqi \
|
||||||
<<< "$container_log"; then
|
'CDBOOT: Cannot boot from CD.*Code: 5' \
|
||||||
|
<<< "$container_log"; then
|
||||||
echo
|
echo
|
||||||
echo "------------------------------------------------------------"
|
echo "------------------------------------------------------------"
|
||||||
echo "The installation media could not be booted."
|
echo "The installation media could not be booted."
|
||||||
exit 1
|
|
||||||
|
if ! handle_failure "The installation media could not be booted."; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
bios_starts="$(
|
bios_starts="$(
|
||||||
@@ -620,7 +878,8 @@ jobs:
|
|||||||
first_bios_start=$SECONDS
|
first_bios_start=$SECONDS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( first_bios_start >= 0 &&
|
if (( failure_checks_disabled == 0 &&
|
||||||
|
first_bios_start >= 0 &&
|
||||||
SECONDS - first_bios_start >= reboot_timeout &&
|
SECONDS - first_bios_start >= reboot_timeout &&
|
||||||
reboots < minimum_reboots )); then
|
reboots < minimum_reboots )); then
|
||||||
echo
|
echo
|
||||||
@@ -629,7 +888,10 @@ jobs:
|
|||||||
"$((reboot_timeout / 60)) minutes after the first BIOS start."
|
"$((reboot_timeout / 60)) minutes after the first BIOS start."
|
||||||
echo "Observed reboots: $reboots"
|
echo "Observed reboots: $reboots"
|
||||||
echo "Required reboots: $minimum_reboots"
|
echo "Required reboots: $minimum_reboots"
|
||||||
exit 1
|
|
||||||
|
if ! handle_failure "The installation did not reboot in time."; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( bios_starts >= boot_loop_limit )) &&
|
if (( bios_starts >= boot_loop_limit )) &&
|
||||||
@@ -642,6 +904,7 @@ jobs:
|
|||||||
echo
|
echo
|
||||||
echo "------------------------------------------------------------"
|
echo "------------------------------------------------------------"
|
||||||
echo "Detected a repeated BIOS boot loop."
|
echo "Detected a repeated BIOS boot loop."
|
||||||
|
echo
|
||||||
echo "SeaBIOS starts: $bios_starts"
|
echo "SeaBIOS starts: $bios_starts"
|
||||||
echo "Hard disk boots: $hard_disk_boots"
|
echo "Hard disk boots: $hard_disk_boots"
|
||||||
echo "DVD boots: $dvd_boots"
|
echo "DVD boots: $dvd_boots"
|
||||||
@@ -649,6 +912,7 @@ jobs:
|
|||||||
echo "Unreadable boot-disk failures: $unreadable_boot_disk"
|
echo "Unreadable boot-disk failures: $unreadable_boot_disk"
|
||||||
echo "No-bootable-device failures: $no_bootable_device"
|
echo "No-bootable-device failures: $no_bootable_device"
|
||||||
echo "BOOTMGR failures: $bootmgr_missing"
|
echo "BOOTMGR failures: $bootmgr_missing"
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -760,4 +1024,5 @@ jobs:
|
|||||||
if: always()
|
if: always()
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
docker rm --force "$TUNNEL" 2>/dev/null || true
|
||||||
docker rm --force "$CONTAINER" 2>/dev/null || true
|
docker rm --force "$CONTAINER" 2>/dev/null || true
|
||||||
|
|||||||
+85
-63
@@ -48,81 +48,101 @@ jobs:
|
|||||||
check() {
|
check() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
local agent="Mozilla/5.0 (X11; Linux x86_64; rv:154.0) Gecko/20100101 Firefox/154.0"
|
local agent="Mozilla/5.0 (X11; Linux x86_64; rv:154.0) Gecko/20100101 Firefox/154.0"
|
||||||
local tmp output pid blocks bytes rc
|
local tmp output pid blocks bytes rc status delay
|
||||||
local start=$SECONDS
|
local attempt=1
|
||||||
|
local attempts=3
|
||||||
|
local start
|
||||||
|
|
||||||
tmp=$(mktemp -d)
|
tmp=$(mktemp -d)
|
||||||
output="$tmp/aria2.log"
|
|
||||||
|
|
||||||
aria2c \
|
while (( attempt <= attempts )); do
|
||||||
--no-conf=true \
|
output="$tmp/aria2.log"
|
||||||
--connect-timeout=30 \
|
rm -f -- "$tmp/probe" "$tmp/probe.aria2" "$output"
|
||||||
--timeout=30 \
|
start=$SECONDS
|
||||||
--max-tries=2 \
|
|
||||||
--retry-wait=2 \
|
aria2c \
|
||||||
--async-dns=false \
|
--no-conf=true \
|
||||||
--follow-metalink=false \
|
--connect-timeout=30 \
|
||||||
--follow-torrent=false \
|
--timeout=30 \
|
||||||
--user-agent="$agent" \
|
--max-tries=2 \
|
||||||
--split=4 \
|
--retry-wait=2 \
|
||||||
--max-connection-per-server=4 \
|
--async-dns=false \
|
||||||
--file-allocation=none \
|
--follow-metalink=false \
|
||||||
--allow-overwrite=true \
|
--follow-torrent=false \
|
||||||
--auto-file-renaming=false \
|
--user-agent="$agent" \
|
||||||
--continue=false \
|
--split=4 \
|
||||||
--dir="$tmp" \
|
--max-connection-per-server=4 \
|
||||||
--out=probe \
|
--file-allocation=none \
|
||||||
--console-log-level=error \
|
--allow-overwrite=true \
|
||||||
--summary-interval=0 \
|
--auto-file-renaming=false \
|
||||||
--download-result=hide \
|
--continue=false \
|
||||||
--show-console-readout=false \
|
--dir="$tmp" \
|
||||||
--enable-color=false \
|
--out=probe \
|
||||||
-- "$url" > "$output" 2>&1 &
|
--console-log-level=error \
|
||||||
pid=$!
|
--summary-interval=0 \
|
||||||
|
--download-result=hide \
|
||||||
|
--show-console-readout=false \
|
||||||
|
--enable-color=false \
|
||||||
|
-- "$url" > "$output" 2>&1 &
|
||||||
|
pid=$!
|
||||||
|
|
||||||
|
while kill -0 "$pid" 2>/dev/null; do
|
||||||
|
if [[ -f "$tmp/probe" ]]; then
|
||||||
|
blocks=$(stat -c '%b' "$tmp/probe" 2>/dev/null || echo 0)
|
||||||
|
bytes=$((blocks * 512))
|
||||||
|
|
||||||
|
if (( bytes >= 1048576 )); then
|
||||||
|
kill "$pid" 2>/dev/null || true
|
||||||
|
wait "$pid" 2>/dev/null || true
|
||||||
|
rm -rf -- "$tmp"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( SECONDS - start >= 60 )); then
|
||||||
|
kill "$pid" 2>/dev/null || true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
|
||||||
|
if wait "$pid"; then
|
||||||
|
rc=0
|
||||||
|
else
|
||||||
|
rc=$?
|
||||||
|
fi
|
||||||
|
|
||||||
|
blocks=0
|
||||||
|
|
||||||
while kill -0 "$pid" 2>/dev/null; do
|
|
||||||
if [[ -f "$tmp/probe" ]]; then
|
if [[ -f "$tmp/probe" ]]; then
|
||||||
blocks=$(stat -c '%b' "$tmp/probe" 2>/dev/null || echo 0)
|
blocks=$(stat -c '%b' "$tmp/probe" 2>/dev/null || echo 0)
|
||||||
bytes=$((blocks * 512))
|
|
||||||
|
|
||||||
if (( bytes >= 1048576 )); then
|
|
||||||
kill "$pid" 2>/dev/null || true
|
|
||||||
wait "$pid" 2>/dev/null || true
|
|
||||||
rm -rf -- "$tmp"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( SECONDS - start >= 60 )); then
|
bytes=$((blocks * 512))
|
||||||
kill "$pid" 2>/dev/null || true
|
|
||||||
break
|
if (( bytes >= 1048576 || (rc == 0 && bytes > 0) )); then
|
||||||
|
rm -rf -- "$tmp"
|
||||||
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 0.2
|
status=$(sed -n 's/.*status=\([0-9][0-9][0-9]\).*/\1/p' "$output" | tail -n 1)
|
||||||
|
|
||||||
|
if (( attempt < attempts )) && [[ "$status" == "429" || "$status" == 5?? ]]; then
|
||||||
|
delay=$((attempt * 15))
|
||||||
|
echo " HTTP ${status}, retrying in ${delay} seconds..." >&2
|
||||||
|
sleep "$delay"
|
||||||
|
attempt=$((attempt + 1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed 's/^/ /' "$output" >&2
|
||||||
|
echo " Downloaded bytes: $bytes" >&2
|
||||||
|
echo " aria2c exit status: $rc" >&2
|
||||||
|
rm -rf -- "$tmp"
|
||||||
|
return 1
|
||||||
done
|
done
|
||||||
|
|
||||||
if wait "$pid"; then
|
|
||||||
rc=0
|
|
||||||
else
|
|
||||||
rc=$?
|
|
||||||
fi
|
|
||||||
|
|
||||||
blocks=0
|
|
||||||
|
|
||||||
if [[ -f "$tmp/probe" ]]; then
|
|
||||||
blocks=$(stat -c '%b' "$tmp/probe" 2>/dev/null || echo 0)
|
|
||||||
fi
|
|
||||||
|
|
||||||
bytes=$((blocks * 512))
|
|
||||||
|
|
||||||
if (( bytes >= 1048576 || (rc == 0 && bytes > 0) )); then
|
|
||||||
rm -rf -- "$tmp"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
sed 's/^/ /' "$output" >&2
|
|
||||||
echo " Downloaded bytes: $bytes" >&2
|
|
||||||
echo " aria2c exit status: $rc" >&2
|
|
||||||
rm -rf -- "$tmp"
|
rm -rf -- "$tmp"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@@ -180,6 +200,8 @@ jobs:
|
|||||||
failed_links+="$url"$'\n'
|
failed_links+="$url"$'\n'
|
||||||
failed_links_html+="<li><a href=\"$url\">$url</a></li>"$'\n'
|
failed_links_html+="<li><a href=\"$url\">$url</a></li>"$'\n'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sleep 2
|
||||||
done < "src/define.sh"
|
done < "src/define.sh"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
Reference in New Issue
Block a user