Skip to content

Commit 01b5017

Browse files
committed
Merge branch 'release/9.3' into 'master'
# Conflicts: # Build/Src/FwBuildTasks/Substitute.cs # Build/mkall.targets # Build/nuget-common/packages.config # Src/LexText/Interlinear/BIRDInterlinearImporter.cs # Src/LexText/Lexicon/ReversalListener.cs # Src/LexText/ParserCore/HCLoader.cs # Src/MasterVersionInfo.txt
2 parents 42a997f + 84d1850 commit 01b5017

564 files changed

Lines changed: 343976 additions & 616895 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.GitHub/copilot-setup-steps.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Reusable workflow to run msbuild tasks on Windows
2+
# Call with: uses: ./.github/workflows/copilot-setup-steps.yml
3+
name: "Copilot: Windows setup steps"
4+
on:
5+
workflow_call:
6+
inputs:
7+
msbuild_args:
8+
required: false
9+
type: string
10+
description: 'Arguments to pass to msbuild (e.g., "FieldWorks.sln /t:RunTests /p:Configuration=Debug")'
11+
# optional secrets or other inputs may be added
12+
13+
jobs:
14+
windows-setup:
15+
runs-on: windows-latest
16+
outputs:
17+
msbuild-path: ${{ steps.find-msbuild.outputs.msbuild-path }}
18+
19+
steps:
20+
- name: Checkout repo
21+
uses: actions/checkout@v4
22+
23+
- name: Find MSBuild (vswhere)
24+
id: find-msbuild
25+
shell: pwsh
26+
run: |
27+
# Try to find msbuild in Visual Studio using vswhere; fallback to common paths
28+
$vsWhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
29+
if (Test-Path $vsWhere) {
30+
$ms = & $vsWhere -latest -requires Microsoft.Component.MSBuild -products * -property installationPath
31+
if ($ms) {
32+
$msbuild = Join-Path $ms 'MSBuild\Current\Bin\MSBuild.exe'
33+
if (-not (Test-Path $msbuild)) {
34+
# older path
35+
$msbuild = Join-Path $ms 'MSBuild\15.0\Bin\MSBuild.exe'
36+
}
37+
}
38+
}
39+
if (-not $msbuild) {
40+
# fallback: try common Program Files paths
41+
$candidates = @(
42+
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\MSBuild.exe",
43+
"${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe",
44+
"${env:ProgramFiles}\MSBuild\14.0\Bin\MSBuild.exe"
45+
)
46+
foreach ($c in $candidates) {
47+
if (Test-Path $c) { $msbuild = $c; break }
48+
}
49+
}
50+
if (-not $msbuild) {
51+
Write-Error "MSBuild not found on runner. Consider installing Visual Studio Build Tools in the runner image or use a self-hosted Windows runner."
52+
exit 1
53+
} else {
54+
Add-Content -Path $env:GITHUB_OUTPUT -Value "msbuild-path=$msbuild"
55+
Write-Host "Found MSBuild at $msbuild"
56+
}
57+
58+
- name: Run msbuild (if args provided)
59+
if: inputs.msbuild_args != '' && inputs.msbuild_args != null
60+
shell: pwsh
61+
run: |
62+
$msbuildPath = "${{ steps.find-msbuild.outputs.msbuild-path }}"
63+
if (-not $msbuildPath) {
64+
Write-Error "MSBuild path not found"
65+
exit 2
66+
}
67+
Write-Host "Running MSBuild: $msbuildPath ${{ inputs.msbuild_args }}"
68+
$args = @()
69+
if ("${{ inputs.msbuild_args }}".Trim() -ne "") {
70+
# Split on spaces, preserving quoted substrings
71+
$args = [System.Management.Automation.PSParser]::Tokenize(${{ toJson(inputs.msbuild_args) }}, [ref]$null) | Where-Object { $_.Type -eq 'String' -or $_.Type -eq 'CommandArgument' } | ForEach-Object { $_.Content }
72+
}
73+
& $msbuildPath @args
74+
if ($LASTEXITCODE -ne 0) {
75+
Write-Error "MSBuild failed with exit code $LASTEXITCODE"
76+
exit $LASTEXITCODE
77+
}
78+
Write-Host "Build completed successfully!" -ForegroundColor Green

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*.designer.cs -whitespace
1111
*.fwdictconfig -whitespace
1212
*.ldml -whitespace
13+
*.py -whitespace
1314
*.patch -whitespace
1415
*.proj -whitespace
1516
*.ReSharper -whitespace
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
name: Base Installer
2+
3+
# Builds the FieldWorks Base Installers (On- and Offline) (x64).
4+
# If `make_release` is true:
5+
# - Uploads installers to https://flex-updates.s3.amazonaws.com/?prefix=jobs/FieldWorks-Win-all-Release-Base.
6+
# - Tags the repository.
7+
# - Creates a GitHub Release of the artifacts required for creating a patch installer on this base.
8+
# Saves the build log as an artifact of the workflow run.
9+
# 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.
10+
11+
on:
12+
schedule:
13+
# Runs every Monday at 02:30 UTC (which is 6:30pm PST / 7:30pm PDT Sunday evening)
14+
- cron: "30 2 * * 1"
15+
workflow_dispatch:
16+
inputs:
17+
fw_ref:
18+
description: 'Commit-ish (branch, tag, SHA) to checkout for the main repository'
19+
required: false
20+
default: ''
21+
helps_ref:
22+
description: 'Commit-ish for helps repository'
23+
required: false
24+
default: 'develop'
25+
installer_ref:
26+
description: 'Commit-ish for PatchableInstaller repository'
27+
required: false
28+
default: 'master'
29+
localizations_ref:
30+
description: 'Commit-ish for localization repository'
31+
required: false
32+
default: 'develop'
33+
lcm_ref:
34+
description: 'Commit-ish for liblcm repository'
35+
required: false
36+
default: 'master'
37+
make_release:
38+
description: 'Should the build archive a release, false by default, should be set to true on a release build.'
39+
required: false
40+
default: 'false'
41+
42+
concurrency:
43+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
44+
cancel-in-progress: true
45+
46+
jobs:
47+
debug_build_and_test:
48+
env:
49+
CROWDIN_API_KEY: ${{ secrets.FLEX_CROWDIN_API }}
50+
LcmRootDir: ${{ github.workspace }}/Localizations/LCM
51+
FILESTOSIGNLATER: ./signExternally
52+
name: Build Debug and run Tests
53+
runs-on: windows-latest
54+
steps:
55+
- name: Compute build number
56+
id: build_number
57+
run: |
58+
$lastJenkins = 1100 # The last base build from jenkins, rounded to the next hundred
59+
$githubRun = $env:GITHUB_RUN_NUMBER
60+
$combined = $lastJenkins + $githubRun
61+
echo "Calculated build number: $combined"
62+
echo "FW_BUILD_NUMBER=$combined" >> $env:GITHUB_ENV
63+
64+
- name: Checkout Files
65+
uses: actions/checkout@v4
66+
id: checkout
67+
with:
68+
ref: ${{ github.event.inputs.fw_ref || github.ref }}
69+
fetch-depth: 0
70+
71+
- name: Checkout Helps
72+
uses: actions/checkout@v4
73+
id: helps-checkout
74+
with:
75+
repository: 'sillsdev/FwHelps'
76+
ref: ${{ github.event.inputs.helps_ref || 'develop' }}
77+
fetch-depth: 0
78+
path: 'DistFiles/Helps'
79+
80+
- name: Checkout PatchableInstaller
81+
uses: actions/checkout@v4
82+
id: installer-checkout
83+
with:
84+
repository: 'sillsdev/genericinstaller'
85+
ref: ${{ github.event.inputs.installer_ref || 'master' }}
86+
fetch-depth: 0
87+
path: 'PatchableInstaller'
88+
89+
- name: Checkout Localizations
90+
uses: actions/checkout@v4
91+
id: loc-checkout
92+
with:
93+
repository: 'sillsdev/FwLocalizations'
94+
ref: ${{ github.event.inputs.localizations_ref || 'develop' }}
95+
fetch-depth: 0
96+
path: 'Localizations'
97+
- name: Checkout liblcm
98+
uses: actions/checkout@v4
99+
id: liblcm-checkout
100+
with:
101+
repository: 'sillsdev/liblcm'
102+
ref: ${{ github.event.inputs.installer_ref || 'master' }}
103+
fetch-depth: 0
104+
path: 'Localizations/LCM'
105+
106+
- name: Download .NET 461 targeting pack
107+
uses: suisei-cn/actions-download-file@818d6b7dc8fe73f2f924b6241f2b1134ca1377d9 # 1.6.0
108+
id: downloadfile # Remember to give an ID if you need the output filename
109+
with:
110+
url: "https://download.microsoft.com/download/F/1/D/F1DEB8DB-D277-4EF9-9F48-3A65D4D8F965/NDP461-DevPack-KB3105179-ENU.exe"
111+
target: public/
112+
113+
- name: Install .NET 461 targeting pack
114+
shell: cmd
115+
working-directory: public
116+
run: NDP461-DevPack-KB3105179-ENU.exe /q
117+
118+
- name: Setup dotnet
119+
uses: actions/setup-dotnet@v4
120+
with:
121+
dotnet-version: |
122+
3.1.x
123+
5.0.x
124+
125+
- name: Install Overcrowdin
126+
shell: cmd
127+
run: |
128+
dotnet tool update -g overcrowdin || dotnet tool install -g overcrowdin
129+
130+
- name: Downgrade Wix Toolset - remove when runner has 3.14.2
131+
run: |
132+
choco uninstall wixtoolset
133+
choco install wixtoolset --version 3.11.2 --allow-downgrade --force
134+
echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
135+
if: github.event_name != 'pull_request'
136+
137+
- name: Prepare for build
138+
shell: cmd
139+
working-directory: Build
140+
run: build64.bat /t:WriteNonlocalDevelopmentPropertiesFile
141+
142+
- name: Build and run tests
143+
id: build_installer
144+
shell: powershell
145+
run: |
146+
cd Build
147+
.\build64.bat /t:BuildBaseInstaller "/property:config=release;action=test;desktopNotAvailable=true" /v:d /bl ^| tee-object -FilePath build.log
148+
cd ..
149+
cd BuildDir
150+
md5sum *.exe > md5.txt
151+
152+
- name: Scan Build Output
153+
shell: powershell
154+
working-directory: Build
155+
run: |
156+
$results = Select-String -Path "build.log" -Pattern "^\s*[1-9][0-9]* Error\(s\)"
157+
if ($results) {
158+
foreach ($result in $results) {
159+
Write-Host "Found errors in build.log $($result.LineNumber): $($result.Line)" -ForegroundColor red
160+
}
161+
exit 1
162+
} else {
163+
Write-Host "No errors found" -ForegroundColor green
164+
exit 0
165+
}
166+
167+
- name: Move installers to staging folder
168+
id: stage_installers
169+
shell: pwsh
170+
run: |
171+
$staging = Join-Path $pwd "Installers"
172+
if (-not (Test-Path $staging)) { New-Item -ItemType Directory -Path $staging | Out-Null }
173+
174+
$offlineExe = Get-ChildItem -Path BuildDir -Filter "FieldWorks_*_Offline_x64.exe" | Select-Object -First 1
175+
$onlineExe = Get-ChildItem -Path BuildDir -Filter "FieldWorks_*_Online_x64.exe" | Select-Object -First 1
176+
177+
if (-not $offlineExe) { throw "FieldWorks_VERSION_Offline_x64.exe not found in BuildDir" }
178+
if (-not $onlineExe) { throw "FieldWorks_VERSION_Online_x64.exe not found in BuildDir" }
179+
180+
Move-Item -Path $offlineExe.FullName -Destination $staging
181+
Move-Item -Path $onlineExe.FullName -Destination $staging
182+
183+
$offlinePath = Join-Path $staging $offlineExe.Name
184+
$onlinePath = Join-Path $staging $onlineExe.Name
185+
186+
"offline_exe=$offlinePath" >> $env:GITHUB_OUTPUT
187+
"online_exe=$onlinePath" >> $env:GITHUB_OUTPUT
188+
189+
- name: Extract burn engines from bundles
190+
shell: cmd
191+
working-directory: Installers
192+
run: |
193+
insignia -ib "${{ steps.stage_installers.outputs.offline_exe }}" -o offline-engine.exe
194+
insignia -ib "${{ steps.stage_installers.outputs.online_exe }}" -o online-engine.exe
195+
196+
- name: Sign Engines
197+
if: github.event_name != 'pull_request'
198+
uses: sillsdev/codesign/trusted-signing-action@v3
199+
with:
200+
credentials: ${{ secrets.TRUSTED_SIGNING_CREDENTIALS }}
201+
files-folder: Installers
202+
files-folder-filter: '*-engine.exe'
203+
description: 'FieldWorks Installer'
204+
description-url: 'https://software.sil.org/fieldworks/'
205+
206+
- name: Reattach Engines
207+
if: github.event_name != 'pull_request'
208+
working-directory: Installers
209+
shell: cmd
210+
run: |
211+
insignia -ab offline-engine.exe "${{ steps.stage_installers.outputs.offline_exe }}" -o "${{ steps.stage_installers.outputs.offline_exe }}"
212+
insignia -ab online-engine.exe "${{ steps.stage_installers.outputs.online_exe }}" -o "${{ steps.stage_installers.outputs.online_exe }}"
213+
214+
- name: Sign Bundles
215+
if: github.event_name != 'pull_request'
216+
uses: sillsdev/codesign/trusted-signing-action@v3
217+
with:
218+
credentials: ${{ secrets.TRUSTED_SIGNING_CREDENTIALS }}
219+
files-folder: Installers
220+
files-folder-filter: FieldWorks_*.exe
221+
description: 'FieldWorks Installer'
222+
description-url: 'https://software.sil.org/fieldworks/'
223+
224+
- name: Configure AWS credentials
225+
if: ${{ inputs.make_release == 'true' }}
226+
uses: aws-actions/configure-aws-credentials@v4
227+
with:
228+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
229+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
230+
aws-region: us-east-1
231+
232+
- name: Upload Installers to S3
233+
if: ${{ inputs.make_release == 'true' }}
234+
shell: pwsh
235+
run: |
236+
$offlineExe = "${{ steps.stage_installers.outputs.offline_exe }}"
237+
$onlineExe = "${{ steps.stage_installers.outputs.online_exe }}"
238+
239+
if (-not (Test-Path $offlineExe)) {
240+
throw "Offline installer not found at $offlineExe"
241+
}
242+
if (-not (Test-Path $onlineExe)) {
243+
throw "Online installer not found at $onlineExe"
244+
}
245+
246+
$offlineFile = Split-Path $offlineExe -Leaf
247+
$onlineFile = Split-Path $onlineExe -Leaf
248+
249+
$s3BasePath = "jobs/FieldWorks-Win-all-Release-Base/$($env:FW_BUILD_NUMBER)"
250+
$offlineS3Key = "$s3BasePath/$offlineFile"
251+
$onlineS3Key = "$s3BasePath/$onlineFile"
252+
253+
aws s3 cp $offlineExe "s3://flex-updates/$offlineS3Key"
254+
Write-Host "Uploaded offline installer to s3://flex-updates/$offlineS3Key"
255+
256+
aws s3 cp $onlineExe "s3://flex-updates/$onlineS3Key"
257+
Write-Host "Uploaded online installer to s3://flex-updates/$onlineS3Key"
258+
259+
- name: Compress Build Artifacts
260+
id: compress_artifacts
261+
if: ${{ inputs.make_release == 'true' }}
262+
run: |
263+
[System.IO.Compression.ZipFile]::CreateFromDirectory(
264+
"${{ github.workspace }}\BuildDir",
265+
"${{ github.workspace }}\BuildDir.zip",
266+
[System.IO.Compression.CompressionLevel]::Optimal,
267+
$false
268+
)
269+
[System.IO.Compression.ZipFile]::CreateFromDirectory(
270+
"${{ github.workspace }}\PatchableInstaller\ProcRunner\ProcRunner\bin\Release\net48",
271+
"${{ github.workspace }}\ProcRunner.zip",
272+
[System.IO.Compression.CompressionLevel]::Optimal,
273+
$false
274+
)
275+
Get-ChildItem "${{ github.workspace }}" -Filter "*.zip" | Select-Object Name, Length
276+
"build_dir_zip=$(("${{ github.workspace }}/BuildDir.zip") -replace '\\','/')" >> $env:GITHUB_OUTPUT
277+
"proc_runner_zip=$(("${{ github.workspace }}/ProcRunner.zip") -replace '\\','/')" >> $env:GITHUB_OUTPUT
278+
279+
280+
- name: Tag, Create Release, and Upload artifacts
281+
if: ${{ inputs.make_release == 'true' }}
282+
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
283+
with:
284+
target_commitish: ${{ github.event.inputs.fw_ref || github.ref }}
285+
tag_name: build-${{ env.FW_BUILD_NUMBER }}
286+
name: "FieldWorks Base Build #${{ env.FW_BUILD_NUMBER }}"
287+
draft: false
288+
prerelease: true
289+
fail_on_unmatched_files: true
290+
files: |
291+
${{ steps.compress_artifacts.outputs.build_dir_zip }}
292+
${{ steps.compress_artifacts.outputs.proc_runner_zip }}
293+
294+
- name: Upload Build Logs
295+
uses: actions/upload-artifact@v4
296+
if: always()
297+
with:
298+
if-no-files-found: warn
299+
name: build-logs
300+
path: |
301+
Build/*.log
302+
Build/*.binlog

0 commit comments

Comments
 (0)