diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index bd17fa46..7d07acdf 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -146,6 +146,26 @@ jobs: printf '%s\n' "$token" > "$RUNNER_TEMP/data/readme.txt" + cat > "$RUNNER_TEMP/oem/sync-log.bat" <<'BATCH' + @echo off + setlocal + + :sync + if exist C:\OEM\install.log ( + copy /Y C:\OEM\install.log \\host.lan\Data\install.tmp >nul 2>&1 + + if not errorlevel 1 ( + move /Y \\host.lan\Data\install.tmp \\host.lan\Data\install.log >nul 2>&1 + ) + ) + + if /I "%~1"=="once" exit /B + if exist C:\OEM\install.done exit /B + + ping 127.0.0.1 -n 6 >nul + goto sync + BATCH + case "$CALLBACK" in powershell) cat > "$RUNNER_TEMP/oem/ready.ps1" <<'POWERSHELL' @@ -156,29 +176,29 @@ jobs: $ErrorActionPreference = "Stop" - $windows = Get-CimInstance Win32_OperatingSystem - $registry = Get-ItemProperty ` - "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" - - $platform = switch ( - $env:PROCESSOR_ARCHITECTURE.ToUpperInvariant() - ) { - "AMD64" { - "x64" - } - "ARM64" { - "arm64" - } - "X86" { - "x86" - } - default { - $env:PROCESSOR_ARCHITECTURE.ToLowerInvariant() - } - } - while ($true) { try { + $windows = Get-CimInstance Win32_OperatingSystem + $registry = Get-ItemProperty ` + "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" + + $platform = switch ( + $env:PROCESSOR_ARCHITECTURE.ToUpperInvariant() + ) { + "AMD64" { + "x64" + } + "ARM64" { + "arm64" + } + "X86" { + "x86" + } + default { + $env:PROCESSOR_ARCHITECTURE.ToLowerInvariant() + } + } + $share = ( Get-Content ` -LiteralPath "\\host.lan\Data\readme.txt" ` @@ -214,6 +234,7 @@ jobs: break } catch { + Write-Output "$(Get-Date -Format s) - Callback retry: $($_.Exception.Message)" Start-Sleep -Seconds 10 } } @@ -221,9 +242,17 @@ jobs: cat > "$RUNNER_TEMP/oem/install.bat" <nul + start "" /B cmd.exe /C C:\OEM\sync-log.bat + powershell.exe -NoProfile -ExecutionPolicy Bypass ^ -File C:\OEM\ready.ps1 ^ -Token "$token" + + set "result=%errorlevel%" + type nul > C:\OEM\install.done + call C:\OEM\sync-log.bat once + exit /B %result% EOF ;; @@ -327,34 +356,41 @@ jobs: Dim temporary Dim destination Dim file - - Set filesystem = CreateObject("Scripting.FileSystemObject") - Set shell = CreateObject("WScript.Shell") - Set locator = CreateObject("WbemScripting.SWbemLocator") - Set service = locator.ConnectServer(".", "root\cimv2") - Set systems = service.ExecQuery("SELECT Caption, Version, BuildNumber FROM Win32_OperatingSystem") - - caption = "" - version = "" - build = "" - - For Each system In systems - caption = CStr(system.Caption) - version = CStr(system.Version) - build = CStr(system.BuildNumber) - Exit For - Next - - edition = ReadRegistry(shell, "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EditionID") - platform = GetPlatform(shell) + Dim success temporary = "\\host.lan\Data\windows.tmp" destination = "\\host.lan\Data\windows.json" Do - On Error Resume Next + success = False - share = ReadTextFile(filesystem, "\\host.lan\Data\readme.txt") + On Error Resume Next + Err.Clear + + Set filesystem = CreateObject("Scripting.FileSystemObject") + Set shell = CreateObject("WScript.Shell") + Set locator = CreateObject("WbemScripting.SWbemLocator") + Set service = locator.ConnectServer(".", "root\cimv2") + Set systems = service.ExecQuery("SELECT Caption, Version, BuildNumber FROM Win32_OperatingSystem") + + caption = "" + version = "" + build = "" + + If Err.Number = 0 Then + For Each system In systems + caption = CStr(system.Caption) + version = CStr(system.Version) + build = CStr(system.BuildNumber) + Exit For + Next + End If + + If Err.Number = 0 Then + edition = ReadRegistry(shell, "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EditionID") + platform = GetPlatform(shell) + share = ReadTextFile(filesystem, "\\host.lan\Data\readme.txt") + End If If Err.Number = 0 Then json = _ @@ -371,7 +407,9 @@ jobs: Set file = filesystem.OpenTextFile(temporary, ForWriting, True) file.Write json file.Close + End If + If Err.Number = 0 Then If filesystem.FileExists(destination) Then filesystem.DeleteFile destination, True End If @@ -380,20 +418,38 @@ jobs: End If If Err.Number = 0 Then - On Error GoTo 0 - Exit Do + success = True + Else + WScript.Echo _ + Now & _ + " - Callback retry: 0x" & _ + Hex(Err.Number) & _ + " - " & _ + Err.Description End If Err.Clear On Error GoTo 0 + If success Then + Exit Do + End If + WScript.Sleep 10000 Loop VBSCRIPT cat > "$RUNNER_TEMP/oem/install.bat" <nul + start "" /B cmd.exe /C C:\OEM\sync-log.bat + cscript.exe //B //NoLogo C:\OEM\ready.vbs "$token" + + set "result=%errorlevel%" + type nul > C:\OEM\install.done + call C:\OEM\sync-log.bat once + exit /B %result% EOF ;; esac @@ -434,6 +490,7 @@ jobs: --env "RAM_SIZE=half" \ --env "CPU_CORES=half" \ --env "CPU_MODEL=$CPU" \ + --env "LOG=Y" \ --env "DISK_SIZE=64G" \ --volume "$RUNNER_TEMP/data:/shared" \ --volume "$RUNNER_TEMP/oem:/oem:ro" \ @@ -450,10 +507,36 @@ jobs: "$CONTAINER" & logs_pid="$!" + guest_log="$RUNNER_TEMP/data/install.log" + + ( + offset=0 + snapshot="$RUNNER_TEMP/install-log.snapshot" + + while true; do + if cp "$guest_log" "$snapshot" 2>/dev/null; then + size="$(stat -c %s "$snapshot" 2>/dev/null || echo 0)" + + if (( size < offset )); then + offset=0 + fi + + if (( size > offset )); then + tail -c "+$((offset + 1))" "$snapshot" 2>/dev/null | + sed -u 's/^/[install.bat] /' || true + offset="$size" + fi + fi + + sleep 2 + done + ) & + + guest_logs_pid="$!" stop_logs() { - kill "$logs_pid" 2>/dev/null || true - wait "$logs_pid" 2>/dev/null || true + kill "$logs_pid" "$guest_logs_pid" 2>/dev/null || true + wait "$logs_pid" "$guest_logs_pid" 2>/dev/null || true } trap stop_logs EXIT diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index f2669685..1ed15bc8 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -23,12 +23,18 @@ jobs: uses: actions/checkout@v7 with: fetch-depth: 0 + - + name: Install aria2 + run: | + if ! command -v aria2c > /dev/null; then + sudo apt-get update -qq + sudo apt-get install -qq --no-install-recommends -y aria2 + fi - name: Validate all download mirrors id: validate run: | errors=0 - skipped=0 tested=0 host="" failed_links="" @@ -37,21 +43,88 @@ jobs: ignored_domains=( files.dog - bobpony.com ) - wget https://github.com/lwthiker/curl-impersonate/releases/download/v0.6.1/curl-impersonate-v0.6.1.x86_64-linux-gnu.tar.gz - tar -xzf curl-impersonate-v0.6.1.x86_64-linux-gnu.tar.gz - sudo cp curl-impersonate-ff /usr/local/bin/ - check() { - local url="$1" http + local url="$1" + 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 start=$SECONDS - http=$(curl-impersonate-ff -sSL -o /dev/null -w "%{http_code}" --max-time 10 -I -- "$url" 2>&1) || http="000" - [[ "$http" == 2* ]] && return 0 + tmp=$(mktemp -d) + output="$tmp/aria2.log" - http=$(curl-impersonate-ff -sSL -o /dev/null -w "%{http_code}" --max-time 10 -r "0-0" -- "$url" 2>&1) || http="000" - [[ "$http" == 2* ]] + aria2c \ + --no-conf=true \ + --connect-timeout=30 \ + --timeout=30 \ + --max-tries=2 \ + --retry-wait=2 \ + --async-dns=false \ + --follow-metalink=false \ + --follow-torrent=false \ + --user-agent="$agent" \ + --split=4 \ + --max-connection-per-server=4 \ + --file-allocation=none \ + --allow-overwrite=true \ + --auto-file-renaming=false \ + --continue=false \ + --dir="$tmp" \ + --out=probe \ + --console-log-level=error \ + --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 + + 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" + return 1 } isIgnoredDomain() { @@ -93,8 +166,7 @@ jobs: seen[$url]=1 if isIgnoredDomain "$url"; then - echo "SKIP: $url (ignored domain)" - skipped=$((skipped + 1)) + echo "SKIP: $url" continue fi @@ -113,10 +185,6 @@ jobs: echo "" printf '%d/%d tested links valid\n' "$((tested - errors))" "$tested" - if (( skipped > 0 )); then - printf '%d link(s) skipped for ignored domains\n' "$skipped" - fi - if (( errors > 0 )); then printf '%d blocking failure(s)\n' "$errors" diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 4f674164..83c16d04 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -41,7 +41,7 @@ jobs: minimum_build: 22000 platform: x64 - - name: Windows 11 IoT Enterprise + - name: Windows 11 IoT version: "11i" expected_caption: Windows 11 expected_edition: IoTEnterpriseS @@ -69,7 +69,7 @@ jobs: minimum_build: 10240 platform: x64 - - name: Windows 10 IoT Enterprise + - name: Windows 10 IoT version: "10i" expected_caption: Windows 10 expected_edition: IoTEnterpriseS @@ -93,38 +93,6 @@ jobs: minimum_build: ${{ matrix.minimum_build }} platform: ${{ matrix.platform }} - tiny: - strategy: - fail-fast: false - matrix: - include: - - name: Core11 - version: "core11" - expected_caption: Windows 11 - minimum_build: 22000 - platform: x64 - - - name: Tiny11 - version: "tiny11" - expected_caption: Windows 11 - minimum_build: 22000 - platform: x64 - - - name: Tiny10 - version: "tiny10" - expected_caption: Windows 10 - minimum_build: 19041 - platform: x64 - - name: ${{ matrix.name }} - uses: ./.github/workflows/install.yml - with: - name: ${{ matrix.name }} - version: ${{ matrix.version }} - expected_caption: ${{ matrix.expected_caption }} - minimum_build: ${{ matrix.minimum_build }} - platform: ${{ matrix.platform }} - server: strategy: fail-fast: false @@ -154,7 +122,7 @@ jobs: minimum_build: 14393 platform: x64 - - name: Windows Server 2012 R2 + - name: Windows Server 2012 version: "2012" expected_caption: Windows Server 2012 R2 minimum_build: 9600 @@ -174,65 +142,56 @@ jobs: fail-fast: false matrix: include: - - name: Windows 7 Ultimate + - name: Windows 7 x64 version: "7u" - cpu: host expected_caption: Windows 7 minimum_build: 7601 platform: x64 - - name: Windows 7 Ultimate x86 + - name: Windows 7 x86 version: "7x86" - cpu: host expected_caption: Windows 7 minimum_build: 7601 platform: x86 - - name: Windows Vista Ultimate + - name: Windows Vista x64 version: "vu" - cpu: host expected_caption: Windows Vista minimum_build: 6002 platform: x64 - - name: Windows Vista Ultimate x86 + - name: Windows Vista x86 version: "vistax86" - cpu: host expected_caption: Windows Vista minimum_build: 6002 platform: x86 - - name: Windows XP Professional + - name: Windows XP x86 version: "xp" - cpu: host expected_caption: Windows XP minimum_build: 2600 platform: x86 - - name: Windows XP Professional x64 + - name: Windows XP x64 version: "xp64" - cpu: host expected_caption: Windows XP minimum_build: 3790 platform: x64 - - name: Windows 2000 Professional + - name: Windows 2000 version: "2k" - cpu: host expected_caption: Windows 2000 minimum_build: 2195 platform: x86 - - name: Windows Server 2008 R2 + - name: Windows Server 2008 version: "2008" - cpu: host expected_caption: Windows Server 2008 R2 minimum_build: 7601 platform: x64 - - name: Windows Server 2003 R2 + - name: Windows Server 2003 version: "2003" - cpu: host expected_caption: Windows Server 2003 minimum_build: 3790 platform: x64 @@ -243,7 +202,38 @@ jobs: name: ${{ matrix.name }} version: ${{ matrix.version }} callback: legacy - cpu: ${{ matrix.cpu }} + expected_caption: ${{ matrix.expected_caption }} + minimum_build: ${{ matrix.minimum_build }} + platform: ${{ matrix.platform }} + + tiny: + strategy: + fail-fast: false + matrix: + include: + - name: Core 11 + version: "core11" + expected_caption: Windows 11 + minimum_build: 22000 + platform: x64 + + - name: Tiny 11 + version: "tiny11" + expected_caption: Windows 11 + minimum_build: 22000 + platform: x64 + + - name: Tiny 10 + version: "tiny10" + expected_caption: Windows 10 + minimum_build: 19041 + platform: x64 + + name: ${{ matrix.name }} + uses: ./.github/workflows/install.yml + with: + name: ${{ matrix.name }} + version: ${{ matrix.version }} expected_caption: ${{ matrix.expected_caption }} minimum_build: ${{ matrix.minimum_build }} platform: ${{ matrix.platform }}