mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-22 17:34:14 +02:00
500 lines
21 KiB
YAML
500 lines
21 KiB
YAML
name: Windows MSI (WiX v7)
|
|
|
|
on:
|
|
# Triggered automatically after a successful Windows build on master
|
|
workflow_run:
|
|
workflows: ["Windows Build"]
|
|
types: [completed]
|
|
branches: [master]
|
|
# Manual trigger still available (e.g. for a specific run_id)
|
|
workflow_dispatch:
|
|
inputs:
|
|
run_id:
|
|
description: "Run ID of 'Windows Build' (leave empty for automatic)"
|
|
required: false
|
|
default: ""
|
|
|
|
jobs:
|
|
build-msi:
|
|
name: Build MSI with WiX v7 (${{ matrix.flavor }})
|
|
runs-on: windows-latest
|
|
# Only runs if Windows Build succeeded (or triggered manually)
|
|
if: >
|
|
github.event_name == 'workflow_dispatch' ||
|
|
github.event.workflow_run.conclusion == 'success'
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
# Single-entry matrix kept on purpose (rather than flattening the job):
|
|
# matrix.flavor is used as part of the MSI ProductCode seed, so changing
|
|
# it would generate a new ProductCode and break upgrade detection for
|
|
# existing installs. Keeping "qt6" here preserves continuity.
|
|
matrix:
|
|
include:
|
|
- flavor: qt6
|
|
portable_artifact: qelectrotech-windows-portable-qt6
|
|
version_source: hardcoded # see note in "Extract version" step
|
|
label_suffix: "-qt6"
|
|
experimental: false
|
|
|
|
permissions:
|
|
contents: write
|
|
pages: write
|
|
id-token: write # Required by SignPath
|
|
|
|
env:
|
|
SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }}
|
|
|
|
outputs:
|
|
qt6_msi: ${{ steps.export.outputs.msi_name_qt6 }}
|
|
|
|
steps:
|
|
# ----------------------------------------------------------------
|
|
# 1. Checkout (to retrieve QElectroTech.wxs and sources)
|
|
# ----------------------------------------------------------------
|
|
- name: Checkout
|
|
uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
# ----------------------------------------------------------------
|
|
# 2. Download the portable artifact for this flavor
|
|
#
|
|
# Wrapped in nick-fields/retry: actions/download-artifact@v8 has
|
|
# shown repeated "Artifact download failed after 5 retries"
|
|
# failures on this cross-workflow download (via run-id) — not a
|
|
# real content/digest problem, just flaky Azure blob delivery.
|
|
# Two separate occurrences observed within days of each other
|
|
# (different artifact IDs/digests, same failure signature), each
|
|
# one enough to fail build-msi outright and block the rest of the
|
|
# pipeline. Retrying the whole download 3x is cheap insurance.
|
|
# Switched to `gh run download` here because nick-fields/retry
|
|
# can only retry a shell command, not re-invoke a `uses:` step.
|
|
# ----------------------------------------------------------------
|
|
- name: Download portable artifact
|
|
uses: nick-fields/retry@v3
|
|
with:
|
|
timeout_minutes: 10
|
|
max_attempts: 3
|
|
retry_wait_seconds: 30
|
|
shell: pwsh
|
|
command: |
|
|
if (Test-Path "artifact\files") { Remove-Item -Recurse -Force "artifact\files" }
|
|
New-Item -ItemType Directory -Force -Path "artifact\files" | Out-Null
|
|
|
|
$runId = "${{ github.event.workflow_run.id || github.event.inputs.run_id || github.run_id }}"
|
|
gh run download $runId `
|
|
--repo "${{ github.repository }}" `
|
|
--name "${{ matrix.portable_artifact }}" `
|
|
--dir "artifact\files"
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Error "gh run download failed (exit $LASTEXITCODE)"
|
|
exit $LASTEXITCODE
|
|
}
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
# ----------------------------------------------------------------
|
|
# 3. Extract version
|
|
# Qt6: hardcoded "0.200.1" here — deliberately NOT parsed from the
|
|
# binary/source, since Qt-version self-detection inside the
|
|
# compiled code proved unreliable (see commit e1aa65f). The CI
|
|
# matrix entry already knows for certain which flavor it is
|
|
# packaging, so the version label is set explicitly at the
|
|
# packaging level instead.
|
|
# ----------------------------------------------------------------
|
|
- name: Extract version
|
|
id: version
|
|
shell: pwsh
|
|
run: |
|
|
if ("${{ matrix.version_source }}" -eq "hardcoded") {
|
|
$ver = "0.200.1"
|
|
} else {
|
|
$src = Get-Content "sources\qetversion.cpp" -Raw -ErrorAction SilentlyContinue
|
|
if ($src -match 'return QVersionNumber\{([^}]+)\}') {
|
|
$ver = $Matches[1] -replace '\s','' -replace ',','.'
|
|
} else {
|
|
# Fallback: CMakeLists.txt
|
|
$cmake = Get-Content "CMakeLists.txt" -Raw
|
|
if ($cmake -match 'project\s*\([^)]*VERSION\s+([\d]+\.[\d]+\.[\d]+)') {
|
|
$ver = $Matches[1]
|
|
} else {
|
|
$ver = "0.0.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Short SHA for the display version
|
|
$sha = git rev-parse --short HEAD 2>$null
|
|
if (-not $sha) { $sha = "unknown" }
|
|
|
|
# Cumulative revision number (same calculation as windows-build.yml)
|
|
$count = git rev-list HEAD --count 2>$null
|
|
$rev = [int]$count + 473
|
|
|
|
# MSI Version only compares Major.Minor.Build (the 4th field is
|
|
# ignored by Windows Installer for upgrade detection), so we
|
|
# inject rev into Build to force a real increase between
|
|
# nightlies and trigger MajorUpgrade's automatic uninstall.
|
|
$verParts = $ver -split '\.'
|
|
$verMsi = "$($verParts[0]).$($verParts[1]).$($rev % 65535)"
|
|
|
|
$flavorTag = "${{ matrix.label_suffix }}"
|
|
$verDisplay = "${ver}${flavorTag}-r${rev}-${sha}_x86_64-win64"
|
|
|
|
echo "VERSION_MSI=$verMsi" >> $env:GITHUB_OUTPUT
|
|
echo "VERSION_DISPLAY=$verDisplay" >> $env:GITHUB_OUTPUT
|
|
Write-Host "Version MSI : $verMsi"
|
|
Write-Host "Version display : $verDisplay"
|
|
|
|
# Qt platform argument: kept from the Qt5 era (QTBUG-83161
|
|
# font-rendering workaround, GDI backend). Qt6 uses DirectWrite by
|
|
# default and does not need it, so this always resolves empty now.
|
|
if ("${{ matrix.flavor }}" -eq "qt5") {
|
|
$qtArgs = "-platform windows:fontengine=freetype"
|
|
} else {
|
|
$qtArgs = ""
|
|
}
|
|
echo "QT_ARGS=$qtArgs" >> $env:GITHUB_OUTPUT
|
|
Write-Host "Qt platform args: '$qtArgs'"
|
|
|
|
# ----------------------------------------------------------------
|
|
# 4. Install WiX v7, accept EULA and install WixUI extension
|
|
# ----------------------------------------------------------------
|
|
- name: Install WiX v7
|
|
shell: pwsh
|
|
run: |
|
|
dotnet tool install --global wix --version 7.0.0
|
|
$toolsPath = [System.IO.Path]::Combine($env:USERPROFILE, '.dotnet', 'tools')
|
|
$env:PATH = "$toolsPath;$env:PATH"
|
|
echo $toolsPath >> $env:GITHUB_PATH
|
|
wix eula accept wix7
|
|
wix extension add WixToolset.UI.wixext/7.0.0
|
|
wix extension add WixToolset.Util.wixext/7.0.0
|
|
Write-Host "WiX v7 installed, EULA accepted, UI + Util extensions added."
|
|
|
|
# ----------------------------------------------------------------
|
|
# 5. Check that the WXS file exists in the repository
|
|
# ----------------------------------------------------------------
|
|
- name: Check WXS file
|
|
shell: pwsh
|
|
run: |
|
|
$wxs = "build-aux\windows\QElectroTech.wxs"
|
|
if (-not (Test-Path $wxs)) {
|
|
Write-Error "WXS file not found: $wxs"
|
|
exit 1
|
|
}
|
|
Write-Host "WXS found: $wxs"
|
|
|
|
# ----------------------------------------------------------------
|
|
# 6. Check the artifact structure and locate files/
|
|
# ----------------------------------------------------------------
|
|
- name: Check artifact structure
|
|
shell: pwsh
|
|
run: |
|
|
$exe = Get-ChildItem -Path "artifact\files" -Filter "qelectrotech.exe" -Recurse | Select-Object -First 1
|
|
if (-not $exe) {
|
|
$exe = Get-ChildItem -Path "artifact\files" -Filter "QElectroTech.exe" -Recurse | Select-Object -First 1
|
|
}
|
|
if (-not $exe) {
|
|
Write-Error "qelectrotech.exe not found in artifact"
|
|
exit 1
|
|
}
|
|
Write-Host "Executable: $($exe.FullName) ($([math]::Round($exe.Length/1MB,1)) MB)"
|
|
$binDir = $exe.Directory.FullName
|
|
$filesDir = Split-Path $binDir -Parent
|
|
echo "FILES_DIR=$filesDir" >> $env:GITHUB_ENV
|
|
Write-Host "FILES_DIR: $filesDir"
|
|
|
|
# ----------------------------------------------------------------
|
|
# 7. Convert LICENSE (GPL-2) to RTF for the WixUI licence screen
|
|
# ----------------------------------------------------------------
|
|
- name: Convert LICENSE to RTF
|
|
shell: pwsh
|
|
run: |
|
|
$licSrc = "LICENSE"
|
|
$licRtf = "$env:TEMP\License.rtf"
|
|
if (-not (Test-Path $licSrc)) {
|
|
Write-Error "LICENSE file not found in repository root"
|
|
exit 1
|
|
}
|
|
$lines = Get-Content $licSrc -Encoding UTF8
|
|
$rtf = New-Object System.Text.StringBuilder
|
|
[void]$rtf.AppendLine('{\rtf1\ansi\ansicpg1252\deff0')
|
|
[void]$rtf.AppendLine('{\fonttbl{\f0\fmodern\fprq1\fcharset0 Courier New;}}')
|
|
[void]$rtf.AppendLine('{\colortbl;\red0\green0\blue0;}')
|
|
[void]$rtf.AppendLine('\f0\fs18\cf1')
|
|
foreach ($line in $lines) {
|
|
$escaped = $line `
|
|
-replace '\\', '\\\\' `
|
|
-replace '\{', '\{' `
|
|
-replace '\}', '\}'
|
|
[void]$rtf.AppendLine("$escaped\par")
|
|
}
|
|
[void]$rtf.AppendLine('}')
|
|
[System.IO.File]::WriteAllText($licRtf, $rtf.ToString(), [System.Text.Encoding]::ASCII)
|
|
echo "LICENSE_RTF=$licRtf" >> $env:GITHUB_ENV
|
|
Write-Host "License.rtf generated: $licRtf"
|
|
|
|
# ----------------------------------------------------------------
|
|
# 8. Replace Lancer QET.bat with the MSI-specific version
|
|
# ----------------------------------------------------------------
|
|
- name: Replace Lancer QET.bat for MSI
|
|
shell: pwsh
|
|
run: |
|
|
$qtArgs = "${{ steps.version.outputs.QT_ARGS }}"
|
|
$bat = "$env:FILES_DIR\Lancer QET.bat"
|
|
$content = "@echo off`r`nstart `"`" `"%~dp0bin\qelectrotech.exe`" --common-elements-dir=`"%~dp0elements/`" --common-tbt-dir=`"%~dp0titleblocks/`" --lang-dir=`"%~dp0lang/`" $qtArgs`r`n"
|
|
[System.IO.File]::WriteAllText($bat, $content, [System.Text.Encoding]::ASCII)
|
|
Write-Host "Lancer QET.bat replaced for MSI installation (qtArgs: '$qtArgs')."
|
|
|
|
# ----------------------------------------------------------------
|
|
# 9. Build the MSI (unsigned at this stage — signing happens below)
|
|
# Qt6 keeps its own ProductCode seed (distinct from the retired Qt5
|
|
# MSI), so a machine that still has the old Qt5 MSI installed gets a
|
|
# separate, coexisting install rather than an unexpected upgrade.
|
|
# ----------------------------------------------------------------
|
|
- name: Build MSI
|
|
shell: pwsh
|
|
run: |
|
|
$version = "${{ steps.version.outputs.VERSION_MSI }}"
|
|
$verDisplay = "${{ steps.version.outputs.VERSION_DISPLAY }}"
|
|
$filesDir = $env:FILES_DIR
|
|
$licRtf = $env:LICENSE_RTF
|
|
$wxs = "build-aux\windows\QElectroTech.wxs"
|
|
$outputName = "QElectroTech-${verDisplay}.msi"
|
|
|
|
$seed = "qelectrotech-msi-${{ matrix.flavor }}-$version"
|
|
$sha1 = [System.Security.Cryptography.SHA1]::Create()
|
|
$hash = $sha1.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($seed))
|
|
$hash[6] = ($hash[6] -band 0x0F) -bor 0x50
|
|
$hash[8] = ($hash[8] -band 0x3F) -bor 0x80
|
|
$productCode = "{$([System.Guid]::new([byte[]]$hash[0..15]).ToString().ToUpper())}"
|
|
|
|
New-Item -ItemType Directory -Force -Path "dist" | Out-Null
|
|
|
|
Write-Host "=== wix build (${{ matrix.flavor }}) ==="
|
|
Write-Host " Version : $version"
|
|
Write-Host " ProductCode : $productCode"
|
|
Write-Host " Output : dist\$outputName"
|
|
|
|
$qtArgs = "${{ steps.version.outputs.QT_ARGS }}"
|
|
|
|
wix build $wxs `
|
|
-arch x64 `
|
|
-d "Version=$version" `
|
|
-d "ProductVersion=$verDisplay" `
|
|
-d "ProductCode=$productCode" `
|
|
-d "FilesDir=$filesDir" `
|
|
-d "LicenseRtf=$licRtf" `
|
|
-d QtPlatformArgs="$qtArgs" `
|
|
-ext WixToolset.UI.wixext `
|
|
-ext WixToolset.Util.wixext `
|
|
-o "dist\$outputName"
|
|
|
|
if (-not (Test-Path "dist\$outputName")) {
|
|
Write-Error "MSI not generated: dist\$outputName"
|
|
exit 1
|
|
}
|
|
|
|
$size = [math]::Round((Get-Item "dist\$outputName").Length / 1MB, 1)
|
|
Write-Host "MSI generated: dist\$outputName ($size MB) OK"
|
|
echo "MSI_NAME=$outputName" >> $env:GITHUB_ENV
|
|
|
|
- name: Upload unsigned MSI artifact (pre-signing)
|
|
id: upload_unsigned
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: qelectrotech-windows-msi-unsigned-${{ matrix.flavor }}
|
|
path: dist\*.msi
|
|
retention-days: 1
|
|
if-no-files-found: error
|
|
|
|
# Qt6 is now signed too (previously excluded while Qt5 was the stable
|
|
# track and Qt6 was experimental-only). The remaining guard is the fork
|
|
# check: forks never have the SignPath secrets, and a fork-originated
|
|
# PR/run must never attempt a signing request.
|
|
# (cf. DieterMayerOSS:fix/msi-signing-fork-guard, d3f60c88)
|
|
# continue-on-error: SignPath's certificate is still pending validation
|
|
# (Sept 2026) — the signing request currently fails with a 500 on the
|
|
# SignPath side. Kept non-blocking so the nightly MSI still ships
|
|
# (unsigned) while the certificate is pending. Remove
|
|
# continue-on-error once the certificate is confirmed active.
|
|
- name: Sign MSI via SignPath
|
|
id: sign
|
|
if: github.repository == 'qelectrotech/qelectrotech-source-mirror' && env.SIGNPATH_API_TOKEN != ''
|
|
continue-on-error: true
|
|
uses: signpath/github-action-submit-signing-request@v2
|
|
with:
|
|
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
|
|
organization-id: ${{ secrets.SIGNPATH_ORGANIZATION_ID }}
|
|
project-slug: 'qelectrotech-source-mirror'
|
|
signing-policy-slug: 'test-signing'
|
|
artifact-configuration-slug: 'MSI'
|
|
github-artifact-id: ${{ steps.upload_unsigned.outputs.artifact-id }}
|
|
wait-for-completion: true
|
|
output-artifact-directory: 'dist\'
|
|
|
|
# If signing succeeded, SignPath already overwrote dist\*.msi with the
|
|
# signed copy (output-artifact-directory above) — nothing to do here.
|
|
# If it failed/was skipped, dist\*.msi is still the unsigned MSI from
|
|
# the "Build MSI" step, so the rest of the pipeline just ships that.
|
|
- name: Report signing status
|
|
if: always()
|
|
shell: pwsh
|
|
run: |
|
|
if ("${{ steps.sign.outcome }}" -eq "success") {
|
|
Write-Host "MSI signed successfully via SignPath."
|
|
} else {
|
|
Write-Warning "MSI signing skipped or failed (outcome: ${{ steps.sign.outcome }}) — shipping UNSIGNED MSI. Likely cause: SignPath certificate still pending validation."
|
|
}
|
|
|
|
- name: Upload signed MSI artifact
|
|
if: always()
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: qelectrotech-windows-msi-${{ matrix.flavor }}
|
|
path: dist\*.msi
|
|
retention-days: 40
|
|
if-no-files-found: error
|
|
|
|
- name: Delete old nightly .msi asset
|
|
# Only run if a new MSI actually exists in dist/ — otherwise the old
|
|
# (still working) nightly .msi would be deleted without anything to
|
|
# replace it, leaving the nightly release with no MSI at all until
|
|
# the next successful build (see windows-msi-pipeline notes,
|
|
# run 35694391567: an upstream artifact-download failure meant
|
|
# dist\*.msi never existed for that run).
|
|
if: always() && hashFiles('dist/*.msi') != ''
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
REPO: ${{ github.repository }}
|
|
run: |
|
|
$pattern = "-qt6.*\\.msi$"
|
|
$names = gh release view nightly --repo $env:REPO --json assets --jq ".assets[] | select(.name | test(`"$pattern`")) | .name"
|
|
foreach ($name in ($names -split "`n" | Where-Object { $_ })) {
|
|
Write-Host "Deleting old asset: $name"
|
|
gh release delete-asset nightly $name --repo $env:REPO --yes
|
|
}
|
|
shell: pwsh
|
|
|
|
- name: Upload MSI to nightly release
|
|
if: always()
|
|
uses: softprops/action-gh-release@v3
|
|
with:
|
|
tag_name: nightly
|
|
files: dist/*.msi
|
|
fail_on_unmatched_files: true
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Export MSI name for page generation
|
|
id: export
|
|
shell: pwsh
|
|
run: |
|
|
$name = "$env:MSI_NAME"
|
|
echo "msi_name_qt6=$name" >> $env:GITHUB_OUTPUT
|
|
|
|
- name: Summary
|
|
if: always()
|
|
shell: pwsh
|
|
run: |
|
|
Write-Host "=== MSI build summary (${{ matrix.flavor }}) ==="
|
|
Write-Host "Version : ${{ steps.version.outputs.VERSION_DISPLAY }}"
|
|
Write-Host "Signed : ${{ steps.sign.outcome == 'success' }}"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Job 2 : Génère et déploie la page GitHub Pages une fois le MSI publié,
|
|
# pour que toutes les URLs soient connues.
|
|
# ---------------------------------------------------------------------------
|
|
deploy-pages:
|
|
needs: build-msi
|
|
runs-on: ubuntu-latest
|
|
# Regenerate the page whenever the MSI job actually ran (success OR
|
|
# packaging/signing failure) — not only on full success.
|
|
# generate-page.py queries the published assets on the "nightly"
|
|
# release itself (line 407: `gh release view nightly --json assets`),
|
|
# so it already handles a missing MSI natively (empty MSI_NAME -> no
|
|
# MSI button on the page). The page only needs the exe/zip already
|
|
# published by windows-build.yml, independent of the MSI's fate.
|
|
# Only "skipped"/"cancelled" are excluded: if build-msi never ran at
|
|
# all (e.g. Windows Build itself failed), there is nothing new to
|
|
# publish and regenerating the page would be pointless.
|
|
if: >
|
|
always() &&
|
|
needs.build-msi.result != 'skipped' &&
|
|
needs.build-msi.result != 'cancelled'
|
|
permissions:
|
|
contents: write
|
|
pages: write
|
|
id-token: write
|
|
|
|
steps:
|
|
- name: Checkout master (for generate-page.py)
|
|
uses: actions/checkout@v7
|
|
with:
|
|
ref: master
|
|
path: source
|
|
sparse-checkout: build-aux/generate-page.py
|
|
sparse-checkout-cone-mode: false
|
|
|
|
- name: Generate download page (index.html)
|
|
shell: bash
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
REPO="${{ github.repository }}"
|
|
|
|
ASSETS=$(gh release view nightly --repo "$REPO" --json assets --jq '.assets[].name')
|
|
|
|
EXE_NAME=$(echo "$ASSETS" | grep 'qt6' | grep '\.exe$' | head -1)
|
|
ZIP_NAME=$(echo "$ASSETS" | grep 'qt6' | grep '\.zip$' | head -1)
|
|
MSI_NAME=$(echo "$ASSETS" | grep 'qt6' | grep '\.msi$' | head -1 || echo "")
|
|
|
|
# Legacy Qt5 assets (no "qt6" in the name): last ever published,
|
|
# frozen — windows-build.yml/windows-msi.yml no longer delete or
|
|
# replace these, so they keep pointing at the same files release
|
|
# after release. Rendered as a separate "legacy" section if present.
|
|
LEGACY_EXE_NAME=$(echo "$ASSETS" | grep -v 'qt6' | grep '\.exe$' | head -1 || echo "")
|
|
LEGACY_ZIP_NAME=$(echo "$ASSETS" | grep -v 'qt6' | grep '\.zip$' | head -1 || echo "")
|
|
LEGACY_MSI_NAME=$(echo "$ASSETS" | grep -v 'qt6' | grep '\.msi$' | head -1 || echo "")
|
|
|
|
BASE="https://github.com/$REPO/releases/download/nightly"
|
|
INSTALLER_URL="$BASE/$EXE_NAME"
|
|
PORTABLE_URL="$BASE/$ZIP_NAME"
|
|
MSI_URL=""
|
|
[ -n "$MSI_NAME" ] && MSI_URL="$BASE/$MSI_NAME"
|
|
|
|
LEGACY_INSTALLER_URL=""
|
|
LEGACY_PORTABLE_URL=""
|
|
LEGACY_MSI_URL=""
|
|
[ -n "$LEGACY_EXE_NAME" ] && LEGACY_INSTALLER_URL="$BASE/$LEGACY_EXE_NAME"
|
|
[ -n "$LEGACY_ZIP_NAME" ] && LEGACY_PORTABLE_URL="$BASE/$LEGACY_ZIP_NAME"
|
|
[ -n "$LEGACY_MSI_NAME" ] && LEGACY_MSI_URL="$BASE/$LEGACY_MSI_NAME"
|
|
|
|
SHA="${{ github.event.workflow_run.head_sha || github.sha }}"
|
|
SHORT="${SHA:0:7}"
|
|
DATE=$(date -u '+%Y-%m-%d %H:%M UTC')
|
|
RUN_URL="https://github.com/$REPO/actions/runs/${{ github.run_id }}"
|
|
RUN_NUMBER="${{ github.run_number }}"
|
|
|
|
export DATE SHORT REPO SHA RUN_URL RUN_NUMBER
|
|
export INSTALLER_URL PORTABLE_URL MSI_URL
|
|
export LEGACY_INSTALLER_URL LEGACY_PORTABLE_URL LEGACY_MSI_URL
|
|
|
|
python3 source/build-aux/generate-page.py
|
|
|
|
- name: Add .nojekyll
|
|
shell: bash
|
|
run: touch gh-pages/.nojekyll
|
|
|
|
- name: Upload GitHub Pages artifact
|
|
uses: actions/upload-pages-artifact@v5
|
|
with:
|
|
path: gh-pages/
|
|
|
|
- name: Deploy to GitHub Pages
|
|
uses: actions/deploy-pages@v4
|