Skip to content

LT-22802: Apply a tool's slice filter list in the Avalonia detail vie… #782

LT-22802: Apply a tool's slice filter list in the Avalonia detail vie…

LT-22802: Apply a tool's slice filter list in the Avalonia detail vie… #782

name: Patch Installer
# Builds the FieldWorks Patch Installer on the specified `base_release`
# If `make_release` is true, uploads installers to https://flex-updates.s3.amazonaws.com/?prefix=jobs/FieldWorks-Win-all-Release-Patch.
# Saves the build log as an artifact of the workflow run.
# Note: FW_BUILD_NUMBER is higher than GITHUB_RUN_NUMBER because it needs to be higher than the build number on artifacts from our previous system.
# Note: FW_BUILD_NUMBER must be higher for patches than their base so that the patch is considered an upgrade.
on:
push:
branches: ["main", "release/**"]
schedule:
# Runs every Monday at 03:30 UTC (which is 8:30pm MST/PDT Sunday evening)
- cron: "30 3 * * 1"
workflow_dispatch:
inputs:
fw_ref:
description: 'Commit-ish (branch, tag, SHA) to checkout for the main repository'
required: false
default: ''
helps_ref:
description: 'Commit-ish for helps repository'
required: false
default: 'develop'
installer_ref:
description: 'Commit-ish for PatchableInstaller repository'
required: false
default: 'master'
localizations_ref:
description: 'Commit-ish for localization repository'
required: false
default: 'develop'
lcm_ref:
description: 'Commit-ish for liblcm repository'
required: false
default: 'master'
# default should be changed to the most recent base release for the release cycle.
# After 9.3 is stable, base_release can be computed from base_build_number, but they need to be independent for bootstrapping patches
# on Jenkins-built bases.
base_release:
description: 'The github release for the base build artifacts (separate only for bootstrapping; should be removed after 9.3 is the stable)'
default: 'build-1452' # Must match base_build_number and its fallbacks.
base_build_number:
description: 'The base build number'
required: false
default: '1452'
make_release:
description: 'Should the release be pushed to s3 - use false for test builds'
required: false
default: 'true'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
upload_strings_build_and_test:
permissions:
contents: read
env:
CROWDIN_API_KEY: ${{ secrets.FLEX_CROWDIN_API }}
LcmRootDir: ${{ github.workspace }}/Localizations/LCMRepo
FILESTOSIGNLATER: ./signExternally
KEEP_INTERMEDIATE_MSI: true
GH_TOKEN: ${{ github.token }}
BASE_BUILD_NUMBER: ${{ inputs.base_build_number || '1452' }}
name: Upload strings for l10n, Build, and run Tests
runs-on: windows-2022
steps:
- name: Compute build number for archival
id: build_number
run: |
$lastJenkins = 2000 # The last patch build from jenkins, rounded to the next hundred
$githubRun = $env:GITHUB_RUN_NUMBER
$combined = $lastJenkins + $githubRun
echo "Calculated build number: $combined"
echo "FW_BUILD_NUMBER=$combined" >> $env:GITHUB_ENV
echo "BuildVersionSegment=$combined" >> $env:GITHUB_ENV
- name: Checkout Files
uses: actions/checkout@v7
id: checkout
with:
ref: ${{ github.event.inputs.fw_ref || github.ref }}
fetch-depth: 0
- name: Checkout Helps
uses: actions/checkout@v7
id: helps-checkout
with:
repository: 'sillsdev/FwHelps'
ref: ${{ github.event.inputs.helps_ref || 'develop' }}
fetch-depth: 0
path: 'DistFiles/Helps'
- name: Checkout PatchableInstaller
uses: actions/checkout@v7
id: installer-checkout
with:
repository: 'sillsdev/genericinstaller'
ref: ${{ github.event.inputs.installer_ref || 'master' }}
fetch-depth: 0
path: 'PatchableInstaller'
- name: Checkout Localizations
uses: actions/checkout@v7
id: loc-checkout
with:
repository: 'sillsdev/FwLocalizations'
ref: ${{ github.event.inputs.localizations_ref || 'develop' }}
fetch-depth: 0
path: 'Localizations'
- name: Checkout liblcm
uses: actions/checkout@v7
id: liblcm-checkout
with:
repository: 'sillsdev/liblcm'
ref: ${{ github.event.inputs.lcm_ref || 'master' }}
fetch-depth: 0
path: 'Localizations/LCMRepo'
- name: Ensure .NET Framework 4.8 targeting pack
shell: pwsh
run: |
# Check registry Release key for .NET Framework 4.8 (Release >= 528040 indicates 4.8)
$targetRelease = 528040
try {
$releaseKey = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" -Name Release -ErrorAction Stop).Release
} catch {
$releaseKey = $null
}
if (-not $releaseKey -or $releaseKey -lt $targetRelease) {
Write-Host "Detected .NET release $releaseKey. Installing .NET Framework 4.8 Developer Pack..."
$installerUrl = "https://download.microsoft.com/download/9/5/0/9500E0A8-3C76-45F9-8D4B-8D2A7F2C1A3A/NDP48-DevPack-KB4486153-ENU.exe"
$installer = Join-Path $env:RUNNER_TEMP "NDP48-DevPack-KB4486153-ENU.exe"
Invoke-WebRequest -Uri $installerUrl -OutFile $installer -UseBasicParsing -TimeoutSec 120
Write-Host "Starting installer..."
$proc = Start-Process -FilePath $installer -ArgumentList "/quiet","/norestart" -Wait -PassThru
if ($proc.ExitCode -ne 0) {
Write-Error "Failed to install .NET 4.8 Developer Pack. ExitCode: $($proc.ExitCode)"
exit $proc.ExitCode
}
Write-Host ".NET 4.8 Developer Pack installation finished."
}
else {
Write-Host ".NET Framework 4.8 (Release=$releaseKey) already present. Skipping install."
}
- name: Setup dotnet
uses: actions/setup-dotnet@v6
with:
dotnet-version: |
3.1.x
5.0.x
- name: Install Overcrowdin
shell: cmd
run: |
dotnet tool update -g overcrowdin || dotnet tool install -g overcrowdin
- name: Downgrade Wix Toolset - remove when runner has 3.14.2
run: |
choco uninstall wixtoolset
choco install wixtoolset --version 3.11.2 --allow-downgrade --force
echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
if: github.event_name != 'pull_request'
- name: Import Base Build Artifacts
shell: pwsh
run: |
$release = "${{ inputs.base_release || 'build-1452' }}"
$repo = "${{ github.repository }}"
Write-Host "Downloading artifacts for release $release from $repo"
# Download BuildDir.zip
gh release download $release --repo $repo --pattern "BuildDir.zip" --dir base-artifacts
if (-not (Test-Path "base-artifacts/BuildDir.zip")) {
throw "BuildDir.zip not found in release '$release'."
}
# Download ProcRunner.zip
gh release download $release --repo $repo --pattern "ProcRunner.zip" --dir base-artifacts
if (-not (Test-Path "base-artifacts/ProcRunner.zip")) {
throw "ProcRunner.zip not found in release '$release'."
}
# Expand BuildDir.zip into BuildDir
Expand-Archive -Path "base-artifacts/BuildDir.zip" -DestinationPath "BuildDir" -Force
Write-Host "Expanded BuildDir.zip -> ./BuildDir"
# Ensure ProcRunner target path exists
$procTarget = "PatchableInstaller/ProcRunner/ProcRunner/bin/Release/net48"
if (-not (Test-Path $procTarget)) {
New-Item -ItemType Directory -Path $procTarget -Force | Out-Null
}
# Expand ProcRunner.zip into the exact net48 folder
Expand-Archive -Path "base-artifacts/ProcRunner.zip" -DestinationPath $procTarget -Force
Write-Host "Expanded ProcRunner.zip -> $procTarget"
# Set an OS feature in the registry that will allow Wix v3 to use temporary files without error
- name: Prepare for build
run: |
# Define paths and the key/value to set
$regPaths = @(
"HKLM:\SOFTWARE\Microsoft\.NETFramework\AppContext",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\AppContext"
)
$valueName = "Switch.System.DisableTempFileCollectionDirectoryFeature"
$expectedValue = "true"
foreach ($path in $regPaths) {
Write-Host "Adding or updating registry value in $path..."
if (-not (Test-Path $path)) {
New-Item -Path $path -Force | Out-Null
}
New-ItemProperty -Path $path -Name $valueName -Value $expectedValue -Type String -Force
}
- name: Upload strings for translation
id: upload
continue-on-error: true
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
shell: powershell
run: |
.\build.ps1 -Target uploadUpdatesForTranslation -Configuration Release *>&1 | Tee-Object -FilePath uploadStrings.log
if ($LASTEXITCODE -ne 0) {
echo "::warning::Upload strings failed with exit code $LASTEXITCODE. See log for details."
}
- name: Build
id: build
shell: powershell
run: |
Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\.NETFramework\AppContext"
.\build.ps1 -BuildPatch -Configuration Release -Verbosity detailed -BuildTests -MsBuildArgs @("/bl") *>&1 | Tee-Object -FilePath build.log
- name: Run tests
shell: powershell
run: |
.\test.ps1 -Configuration Release -NoBuild -TestFilter 'TestCategory!=DesktopRequired&TestCategory!=RenderBenchmark' *>&1 | Tee-Object -FilePath test.log
- name: Analyze Build Log
if: always() && steps.build.outcome != 'skipped'
shell: pwsh
run: |
python scripts/tools/analyze_build_log.py build.log --workspace "${{ github.workspace }}"
- name: Find patch installer
id: find_patch
shell: pwsh
run: |
$patch = Get-ChildItem -Path BuildDir -Filter "FieldWorks_*.msp" | Select-Object -First 1
if (-not $patch) { throw "Patch (.msp) file not found in BuildDir" }
$patchPath = $patch.FullName
"patch_file=$patchPath" >> $env:GITHUB_OUTPUT
"patch_version=$(($patch.Name -split '_')[1])" >> $env:GITHUB_OUTPUT
"ledger_file=$($patchPath -replace '\.msp$', '_components.tsv')" >> $env:GITHUB_OUTPUT
"update_msi=$((Get-ChildItem PatchableInstaller/CreateUpdatePatch/Update -Filter '*.msi' | Select-Object -First 1).FullName)" >> $env:GITHUB_OUTPUT
"master_msi=$((Get-ChildItem PatchableInstaller/CreateUpdatePatch/Master -Filter '*.msi' | Select-Object -First 1).FullName)" >> $env:GITHUB_OUTPUT
# Patch component identity must remain stable across the base and previous patch.
- name: Check patch keeps base and previous-patch components
shell: pwsh
run: |
.\scripts\Installer\Check-PatchComponentLedger.ps1 `
-MasterMsi "${{ steps.find_patch.outputs.master_msi }}" `
-UpdateMsi "${{ steps.find_patch.outputs.update_msi }}" `
-BaseBuildNumber $env:BASE_BUILD_NUMBER `
-PatchVersion "${{ steps.find_patch.outputs.patch_version }}" `
-OutLedger "${{ steps.find_patch.outputs.ledger_file }}"
- name: Sign Patch
if: github.event_name != 'pull_request'
uses: sillsdev/codesign/trusted-signing-action@v3
with:
credentials: ${{ secrets.TRUSTED_SIGNING_CREDENTIALS }}
files-folder: BuildDir
files-folder-filter: '*.msp'
description: 'FieldWorks Patch Installer'
description-url: 'https://software.sil.org/fieldworks/'
- name: Configure AWS credentials
# Use inputs if defined but default to true
if: ${{ (inputs.make_release || 'true') == 'true' }}
uses: aws-actions/configure-aws-credentials@v6
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Upload Patch to S3
# Use inputs if defined but default to true
if: ${{ (inputs.make_release || 'true') == 'true' }}
shell: pwsh
run: |
$patchPath = "${{ steps.find_patch.outputs.patch_file }}"
if (-not (Test-Path $patchPath)) {
throw "Patch file not found at $patchPath"
}
$ledgerPath = "${{ steps.find_patch.outputs.ledger_file }}"
if (-not (Test-Path $ledgerPath)) {
throw "Ledger file not found at $ledgerPath"
}
$patchFile = Split-Path $patchPath -Leaf
$s3Key = "jobs/FieldWorks-Win-all-Release-Patch/$($env:FW_BUILD_NUMBER)/$patchFile"
$ledgerKey = "jobs/FieldWorks-Win-all-Release-Patch/$($env:FW_BUILD_NUMBER)/$(Split-Path $ledgerPath -Leaf)"
aws s3 cp $ledgerPath "s3://flex-updates/$ledgerKey"
if ($LASTEXITCODE -ne 0) {
throw "Ledger upload failed with exit code $LASTEXITCODE"
}
Write-Host "Uploaded to s3://flex-updates/$ledgerKey"
aws s3 cp $patchPath "s3://flex-updates/$s3Key"
if ($LASTEXITCODE -ne 0) {
throw "Patch upload failed with exit code $LASTEXITCODE"
}
Write-Host "Uploaded to s3://flex-updates/$s3Key"
- name: Upload Build Logs
uses: actions/upload-artifact@v7
if: always()
with:
if-no-files-found: warn
name: build-logs
path: |
./*.log
./*.binlog
./Output/**/*.log
./Output/**/*.log.stderr
./PatchableInstaller/CreateUpdatePatch/Master/AppHarvest.wxs
./PatchableInstaller/CreateUpdatePatch/Update/AppHarvest.wxs