Fix UEFI BootNext compatibility probing #21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Continuous integration | |
| on: | |
| workflow_call: | |
| push: | |
| branches: | |
| - dev | |
| pull_request: | |
| branches: | |
| - dev | |
| workflow_dispatch: | |
| # Read access is the workflow default. Only the release job receives write access. | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| quality: | |
| name: Python tests and source quality | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Python | |
| uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: "3.13" | |
| cache: pip | |
| cache-dependency-path: | | |
| auto_tests/requirements.txt | |
| auto_tests/requirements-dev.txt | |
| - name: Install test dependencies | |
| working-directory: auto_tests | |
| run: python -m pip install --requirement requirements-dev.txt | |
| - name: Lint Python | |
| working-directory: auto_tests | |
| run: python -m ruff check app tests ../assets/live/*.py ../iso-tools/*.py | |
| - name: Check Python formatting | |
| working-directory: auto_tests | |
| run: python -m ruff format --check app tests ../assets/live/*.py ../iso-tools/*.py | |
| - name: Run Python test suite with coverage | |
| working-directory: auto_tests | |
| run: python -m pytest --cov=app --cov-report=term-missing --cov-fail-under=70 | |
| - name: Validate shell script syntax | |
| shell: bash | |
| run: | | |
| set -Eeuo pipefail | |
| while IFS= read -r -d '' script; do | |
| bash -n "$script" | |
| done < <(git ls-files -z '*.sh') | |
| - name: Run ShellCheck | |
| shell: bash | |
| run: | | |
| set -Eeuo pipefail | |
| git ls-files -z '*.sh' | xargs -0 --no-run-if-empty shellcheck -x -S warning | |
| - name: Validate versioned JSON contracts | |
| shell: bash | |
| run: | | |
| set -Eeuo pipefail | |
| python -m json.tool schemas/installation-plan.schema.json >/dev/null | |
| python -m json.tool schemas/installation-state.schema.json >/dev/null | |
| wpf: | |
| name: Build WPF (.NET Framework 4.8) | |
| runs-on: windows-2022 | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Add Visual Studio MSBuild to PATH | |
| uses: microsoft/setup-msbuild@30375c66a4eea26614e0d39710365f22f8b0af57 # v3 | |
| with: | |
| vs-version: "[17.0,18.0)" | |
| - name: Verify .NET Framework 4.8 build tools | |
| shell: pwsh | |
| run: | | |
| $referenceAssemblies = Join-Path ${env:ProgramFiles(x86)} ` | |
| 'Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8' | |
| if (-not (Test-Path -LiteralPath $referenceAssemblies -PathType Container)) { | |
| throw ".NET Framework 4.8 targeting pack is missing: $referenceAssemblies" | |
| } | |
| msbuild -version | |
| - name: Validate PowerShell syntax | |
| shell: pwsh | |
| run: | | |
| $failures = [System.Collections.Generic.List[string]]::new() | |
| Get-ChildItem -Path Scripts, auto_tests/app/scripts, PowerShell.Tests -Recurse -File | | |
| Where-Object { $_.Extension -in '.ps1', '.psm1' } | | |
| ForEach-Object { | |
| $tokens = $null | |
| $errors = $null | |
| [void][System.Management.Automation.Language.Parser]::ParseFile( | |
| $_.FullName, | |
| [ref]$tokens, | |
| [ref]$errors | |
| ) | |
| foreach ($errorRecord in $errors) { | |
| $failures.Add("$($_.FullName): $($errorRecord.Message)") | |
| } | |
| } | |
| if ($failures.Count -gt 0) { | |
| throw ($failures -join [Environment]::NewLine) | |
| } | |
| - name: Analyze PowerShell | |
| shell: pwsh | |
| run: | | |
| Install-Module -Name PSScriptAnalyzer -RequiredVersion 1.25.0 ` | |
| -Scope CurrentUser -Force -Repository PSGallery | |
| $findings = @( | |
| Invoke-ScriptAnalyzer ` | |
| -Path Scripts ` | |
| -Recurse ` | |
| -Settings PSScriptAnalyzerSettings.psd1 ` | |
| -Severity Error, Warning | |
| Invoke-ScriptAnalyzer ` | |
| -Path auto_tests/app/scripts ` | |
| -Recurse ` | |
| -Settings PSScriptAnalyzerSettings.psd1 ` | |
| -Severity Error, Warning | |
| Invoke-ScriptAnalyzer ` | |
| -Path PowerShell.Tests ` | |
| -Recurse ` | |
| -Settings PSScriptAnalyzerSettings.psd1 ` | |
| -Severity Error, Warning | |
| ) | |
| $findings | Format-Table -AutoSize | |
| if ($findings.Count -gt 0) { | |
| throw "PSScriptAnalyzer reported $($findings.Count) finding(s)." | |
| } | |
| - name: Run PowerShell contract tests | |
| shell: pwsh | |
| run: | | |
| Install-Module -Name Pester -RequiredVersion 6.0.1 ` | |
| -Scope CurrentUser -Force -Repository PSGallery | |
| $configuration = New-PesterConfiguration | |
| $configuration.Run.Path = 'PowerShell.Tests' | |
| $configuration.Run.Exit = $true | |
| $configuration.Output.Verbosity = 'Normal' | |
| Invoke-Pester -Configuration $configuration | |
| - name: Build Libertix.exe | |
| shell: pwsh | |
| run: >- | |
| msbuild Libertix.sln | |
| /restore | |
| /m | |
| /warnaserror | |
| /p:Configuration=Release | |
| '/p:Platform=Any CPU' | |
| /verbosity:minimal | |
| - name: Run C# contract tests | |
| shell: pwsh | |
| run: >- | |
| dotnet test Libertix.Tests\Libertix.Tests.csproj | |
| --configuration Release | |
| --no-build | |
| --no-restore | |
| --verbosity minimal | |
| - name: Verify WPF output | |
| shell: pwsh | |
| run: | | |
| $executable = 'bin\Release\Libertix.exe' | |
| if (-not (Test-Path -LiteralPath $executable -PathType Leaf)) { | |
| throw "Expected WPF executable was not produced: $executable" | |
| } | |
| $hash = Get-FileHash -Algorithm SHA256 -LiteralPath $executable | |
| "Libertix.exe SHA-256: $($hash.Hash.ToLowerInvariant())" | | |
| Tee-Object -FilePath $env:GITHUB_STEP_SUMMARY -Append | |
| - name: Upload WPF build | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: Libertix-wpf-${{ github.sha }} | |
| path: bin/Release/** | |
| if-no-files-found: error | |
| retention-days: 14 | |
| compression-level: 9 | |
| iso: | |
| name: Build and verify BIOS and UEFI mini-ISO | |
| needs: | |
| - quality | |
| - wpf | |
| # The ISO builder requires a privileged Docker container. Do not execute | |
| # untrusted pull-request code with that privilege. | |
| if: github.event_name != 'pull_request' && github.ref == 'refs/heads/dev' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 150 | |
| steps: | |
| - name: Check out source | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Verify Docker and disk capacity | |
| shell: bash | |
| run: | | |
| set -Eeuo pipefail | |
| docker version | |
| available_bytes="$(df -B1 --output=avail "$GITHUB_WORKSPACE" | tail -n 1 | tr -d ' ')" | |
| required_bytes="$((12 * 1024 * 1024 * 1024))" | |
| printf 'Available workspace capacity: %s bytes\n' "$available_bytes" | |
| if (( available_bytes < required_bytes )); then | |
| printf 'At least %s bytes are required for both full ISO builds.\n' \ | |
| "$required_bytes" >&2 | |
| exit 1 | |
| fi | |
| - name: Build and verify both mini-ISO images | |
| shell: bash | |
| run: ./iso-tools/build-isos-docker.sh all | |
| - name: Record ISO checksums | |
| shell: bash | |
| run: | | |
| set -Eeuo pipefail | |
| test -s libertix-installer-bios.iso | |
| test -s libertix-installer-uefi.iso | |
| sha256sum \ | |
| libertix-installer-bios.iso \ | |
| libertix-installer-uefi.iso \ | |
| | tee libertix-isos.sha256 | |
| cat libertix-isos.sha256 >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload verified mini-ISO images | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: Libertix-mini-isos-${{ github.sha }} | |
| path: | | |
| libertix-installer-bios.iso | |
| libertix-installer-uefi.iso | |
| libertix-isos.sha256 | |
| if-no-files-found: error | |
| retention-days: 7 | |
| compression-level: 0 | |
| release: | |
| name: Publish dev alpha prerelease | |
| needs: | |
| - quality | |
| - wpf | |
| - iso | |
| if: >- | |
| github.ref == 'refs/heads/dev' && | |
| (github.event_name == 'push' || github.event_name == 'workflow_dispatch') | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download WPF build | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: Libertix-wpf-${{ github.sha }} | |
| path: release-input/wpf | |
| - name: Download verified mini-ISO images | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: Libertix-mini-isos-${{ github.sha }} | |
| path: release-input/iso | |
| - name: Prepare release assets | |
| shell: bash | |
| run: | | |
| set -Eeuo pipefail | |
| test -d release-input/wpf | |
| test -s release-input/iso/libertix-installer-bios.iso | |
| test -s release-input/iso/libertix-installer-uefi.iso | |
| mkdir -p release-assets | |
| ( | |
| cd release-input/wpf | |
| zip -9 -q -r "$GITHUB_WORKSPACE/release-assets/Libertix-wpf.zip" . | |
| ) | |
| cp -- \ | |
| release-input/iso/libertix-installer-bios.iso \ | |
| release-input/iso/libertix-installer-uefi.iso \ | |
| release-assets/ | |
| test -s release-assets/Libertix-wpf.zip | |
| - name: Publish alpha prerelease | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| set -Eeuo pipefail | |
| tag="${GITHUB_SHA:0:7}" | |
| title="Alpha $tag" | |
| commit_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$GITHUB_SHA" | |
| notes="Automated Libertix alpha build for commit [$tag]($commit_url)." | |
| assets=( | |
| release-assets/Libertix-wpf.zip | |
| release-assets/libertix-installer-bios.iso | |
| release-assets/libertix-installer-uefi.iso | |
| ) | |
| if gh release view "$tag" >/dev/null 2>&1; then | |
| gh release edit "$tag" \ | |
| --target "$GITHUB_SHA" \ | |
| --title "$title" \ | |
| --notes "$notes" \ | |
| --prerelease | |
| gh release upload "$tag" "${assets[@]}" --clobber | |
| else | |
| gh release create "$tag" "${assets[@]}" \ | |
| --target "$GITHUB_SHA" \ | |
| --title "$title" \ | |
| --notes "$notes" \ | |
| --prerelease | |
| fi | |
| - name: Keep the three newest dev alpha prereleases | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| set -Eeuo pipefail | |
| mapfile -t stale_tags < <( | |
| gh release list \ | |
| --limit 100 \ | |
| --json tagName,isPrerelease,createdAt \ | |
| --jq '[.[] | select(.isPrerelease == true and (.tagName | test("^[0-9a-f]{7}$")))] | sort_by(.createdAt) | reverse | .[3:][] | .tagName' | |
| ) | |
| for stale_tag in "${stale_tags[@]}"; do | |
| gh release delete "$stale_tag" --cleanup-tag --yes | |
| done |