Skip to content

Commit 99445b8

Browse files
authored
Use GitHub Actions to build and test NVDA (#17728)
fixes #10516 Summary of the issue: Currently Appveyor is used to build and test NVDA. GitHub Actions may be preferred, since it's on GitHub and may be easier to use. Description of user facing changes None Description of development approach New GitHub Workflows: .github/workflows/testAndPublish.yml: CI / CD for NVDA - to replace AppVeyor .github/workflows/scan-release.yml: For scanning published releases with Virus Total Pre-commit Configuration: .pre-commit-config.yaml: Updated to consider changes to pyproject.toml when running license check files. Tests: tests/checkPot.py: Updated print statements to direct output to stderr for certain messages. tests/unit/test_checkPot/__init__.py: Adjusted the redirection of stdout and stderr for ordered output and modified assertions. Project Configuration: pyproject.toml: Removed several dependencies from the ignore_packages list (due to Apache compatibility now claimed) and adjusted the licenses section.
1 parent 96a58d6 commit 99445b8

14 files changed

+548
-27
lines changed

.github/workflows/testAndPublish.yml

+311
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
name: CI/CD
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- beta
8+
- rc
9+
- 'try-**'
10+
tags:
11+
- 'release-**'
12+
13+
pull_request:
14+
branches:
15+
- master
16+
- beta
17+
- rc
18+
19+
workflow_dispatch:
20+
21+
concurrency:
22+
group: ${{ github.workflow }}-${{ github.ref }}
23+
cancel-in-progress: true
24+
25+
env:
26+
START_BUILD_NUMBER: 50000
27+
pullRequestNumber: ${{ github.event_name == 'pull_request' && github.event.number || 0 }}
28+
scons_publisher: NV Access
29+
# Comment out any of the feature_* variables to disable the respective build feature.
30+
# They are checked for existence of content, not specific value.
31+
# feature_buildSymbols: configured
32+
# feature_uploadSymbolsToMozilla: configured
33+
# feature_buildAppx: configured
34+
# feature_crowdinSync: configured
35+
# feature_signing: configured
36+
37+
jobs:
38+
buildNVDA:
39+
name: Build NVDA
40+
runs-on: windows-latest
41+
steps:
42+
- name: Checkout NVDA
43+
uses: actions/checkout@v4
44+
with:
45+
submodules: true
46+
- name: Install dependencies
47+
uses: actions/setup-python@v5
48+
with:
49+
python-version: '3.11'
50+
architecture: x86
51+
- name: Set version variables
52+
run: ci/scripts/setBuildVersionVars.ps1
53+
- name: Set scons args
54+
run: ci/scripts/setSconsArgs.ps1
55+
- name: Prepare source code
56+
shell: cmd
57+
run: scons source %sconsArgs% ${{ !runner.debug && '--all-cores' || '-j1' }}
58+
- name: Prepare for tests
59+
run: ci/scripts/tests/beforeTests.ps1
60+
- name: Cache scons build
61+
uses: actions/cache/save@v4
62+
with:
63+
path: ${{ github.workspace }}
64+
key: ${{ github.ref }}-${{ github.run_id }}
65+
66+
checkPot:
67+
name: Check translator comments
68+
runs-on: windows-latest
69+
needs: buildNVDA
70+
steps:
71+
- name: Checkout cached build
72+
uses: actions/cache/restore@v4
73+
with:
74+
path: ${{ github.workspace }}
75+
key: ${{ github.ref }}-${{ github.run_id }}
76+
fail-on-cache-miss: true
77+
- name: Check comments for translators
78+
run: ci/scripts/tests/translationCheck.ps1
79+
- name: Upload artifact
80+
if: ${{ success() || failure() }}
81+
uses: actions/upload-artifact@v4
82+
with:
83+
name: makePot results
84+
path: |
85+
output/nvda.pot
86+
output/potSourceFileList.txt
87+
88+
licenseCheck:
89+
name: Check license compatibility of dependencies
90+
runs-on: windows-latest
91+
needs: buildNVDA
92+
steps:
93+
- name: Checkout cached build
94+
uses: actions/cache/restore@v4
95+
with:
96+
path: ${{ github.workspace }}
97+
key: ${{ github.ref }}-${{ github.run_id }}
98+
fail-on-cache-miss: true
99+
- name: License check
100+
run: ci/scripts/tests/licenseCheck.ps1
101+
102+
unitTests:
103+
name: Run unit tests
104+
runs-on: windows-latest
105+
needs: buildNVDA
106+
steps:
107+
- name: Checkout cached build
108+
uses: actions/cache/restore@v4
109+
with:
110+
path: ${{ github.workspace }}
111+
key: ${{ github.ref }}-${{ github.run_id }}
112+
fail-on-cache-miss: true
113+
- name: Run unit tests
114+
run: ci/scripts/tests/unitTests.ps1
115+
- name: Replace relative paths in unit test results
116+
if: ${{ success() || failure() }}
117+
# Junit reports fail on these
118+
shell: bash
119+
run: sed -i 's|file="..\\|file="|g' testOutput/unit/unitTests.xml
120+
- name: Upload artifact
121+
if: ${{ success() || failure() }}
122+
uses: actions/upload-artifact@v4
123+
with:
124+
name: Unit tests results
125+
path: testOutput/unit/unitTests.xml
126+
- name: Publish unit test report
127+
uses: mikepenz/action-junit-report@v5
128+
if: ${{ success() || failure() }}
129+
with:
130+
check_name: Unit tests
131+
detailed_summary: true
132+
annotate_only: true
133+
report_paths: testOutput/unit/unitTests.xml
134+
135+
createLauncher:
136+
name: Create launcher
137+
runs-on: windows-latest
138+
needs: buildNVDA
139+
steps:
140+
- name: Checkout cached build
141+
uses: actions/cache/restore@v4
142+
with:
143+
path: ${{ github.workspace }}
144+
key: ${{ github.ref }}-${{ github.run_id }}
145+
fail-on-cache-miss: true
146+
- name: Set version variables
147+
run: ci/scripts/setBuildVersionVars.ps1
148+
- name: Set scons args
149+
run: ci/scripts/setSconsArgs.ps1
150+
- name: Prepare source code for launcher
151+
shell: cmd
152+
run: scons %sconsOutTargets% %sconsArgs% ${{ !runner.debug && '--all-cores' || '-j1'}}
153+
- name: Export package list
154+
shell: cmd
155+
run: .\venvUtils\exportPackageList.bat output\installed_python_packages.txt
156+
- name: Upload launcher
157+
id: uploadLauncher
158+
uses: actions/upload-artifact@v4
159+
with:
160+
name: NVDA launcher
161+
path: output/nvda*.exe
162+
- name: Upload documentation artifacts
163+
uses: actions/upload-artifact@v4
164+
id: uploadDocsArtifacts
165+
with:
166+
name: Documentation files
167+
path: |
168+
output/devDocs
169+
output/*.html
170+
output/*.css
171+
- name: Upload build artifacts
172+
uses: actions/upload-artifact@v4
173+
id: uploadBuildArtifacts
174+
with:
175+
name: Controller client and packaging metadata
176+
path: |
177+
output/nvda*controllerClient.zip
178+
output/library_modules.txt
179+
output/installed_python_packages.txt
180+
- name: Add job summary
181+
shell: bash
182+
run: |
183+
echo "* [Download the NVDA launcher](${{ steps.uploadLauncher.outputs.artifact-url }}) (${{ steps.uploadLauncher.outputs.artifact-digest }})" >> $GITHUB_STEP_SUMMARY
184+
echo "* [Download the documentation](${{ steps.uploadDocsArtifacts.outputs.artifact-url }})" >> $GITHUB_STEP_SUMMARY
185+
echo "* [Download the other build artifacts](${{ steps.uploadBuildArtifacts.outputs.artifact-url }})" >> $GITHUB_STEP_SUMMARY
186+
echo " * Controller client" >> $GITHUB_STEP_SUMMARY
187+
echo " * Packaging metadata (library modules, installed python packages)" >> $GITHUB_STEP_SUMMARY
188+
189+
systemTests:
190+
name: Run system tests
191+
runs-on: windows-latest
192+
needs: createLauncher
193+
steps:
194+
- name: Checkout cached build
195+
uses: actions/cache/restore@v4
196+
with:
197+
path: ${{ github.workspace }}
198+
key: ${{ github.ref }}-${{ github.run_id }}
199+
fail-on-cache-miss: true
200+
- name: Get NVDA launcher
201+
id: getLauncher
202+
uses: actions/download-artifact@v4
203+
with:
204+
name: NVDA launcher
205+
path: output
206+
- name: Install NVDA
207+
run: ci/scripts/installNVDA.ps1
208+
env:
209+
nvdaLauncherDir: ${{ steps.getLauncher.outputs.download-path }}
210+
- name: Upload install log
211+
if: ${{ success() || failure() }}
212+
uses: actions/upload-artifact@v4
213+
with:
214+
name: Install log
215+
path: |
216+
testOutput/install
217+
!testOutput/install/nvda_install_temp.log
218+
- name: Run system tests
219+
run: ci/scripts/tests/systemTests.ps1
220+
env:
221+
nvdaLauncherDir: ${{ steps.getLauncher.outputs.download-path }}
222+
- name: Upload system tests results
223+
if: ${{ success() || failure() }}
224+
uses: actions/upload-artifact@v4
225+
with:
226+
name: System tests results
227+
path: testOutput/system
228+
- name: Publish system test report
229+
uses: mikepenz/action-junit-report@v5
230+
if: ${{ success() || failure() }}
231+
with:
232+
check_name: System tests
233+
detailed_summary: true
234+
annotate_only: true
235+
report_paths: testOutput/system/systemTests.xml
236+
237+
cleanupCache:
238+
# Cache deletion on pull_request events cannot occur on PRs from forks
239+
# as PRs from forks do not get write permissions from pull_request events.
240+
# Alternatively, we can change the event trigger to pull_request_target,
241+
# however that might introduce security risks as it grants fork PRs greater permissions.
242+
# In these cases we can always let GitHub handle cache deletion:
243+
# auto deletion after 7 days or limits are hit
244+
name: Cleanup cache
245+
permissions:
246+
actions: write
247+
needs: [checkPot, licenseCheck, unitTests, systemTests]
248+
if: ${{ always() && (github.event_name == 'push' || github.event.pull_request.head.repo.owner == github.repository_owner) }}
249+
runs-on: ubuntu-latest
250+
steps:
251+
- name: Cleanup cache
252+
shell: bash
253+
run: gh cache delete ${{ github.ref }}-${{ github.run_id }}
254+
env:
255+
GH_TOKEN: ${{ github.token }}
256+
GH_REPO: ${{ github.repository }}
257+
258+
release:
259+
name: Release NVDA
260+
permissions:
261+
contents: write
262+
runs-on: ubuntu-latest
263+
needs: [checkPot, licenseCheck, unitTests, systemTests]
264+
if: startsWith(github.ref_name, 'release-')
265+
steps:
266+
- name: Get normalized tag names
267+
id: getReleaseNotes
268+
shell: bash
269+
run: |
270+
echo RELEASE_NAME=$GITHUB_REF_NAME | sed 's/release-//g' >> $GITHUB_OUTPUT
271+
echo NORMALIZED_TAG_NAME=$GITHUB_REF_NAME | sed 's/\./-/g' | sed 's/release-//g' >> $GITHUB_OUTPUT
272+
- name: Get NVDA launcher
273+
uses: actions/download-artifact@v4
274+
with:
275+
name: NVDA launcher
276+
path: output
277+
- name: VirusTotal Scan
278+
id: virusTotal
279+
uses: crazy-max/ghaction-virustotal@v4
280+
with:
281+
vt_api_key: ${{ secrets.VT_API_KEY }}
282+
files: output/nvda*.exe
283+
- name: Get normalized VT url
284+
id: getVTUrl
285+
shell: bash
286+
run: |
287+
vtUrl=$(echo ${{ steps.virusTotal.outputs.analysis }} | sed -E 's/([^=]*)=([^,]*).*/\2/')
288+
echo VT_URL=$vtUrl >> $GITHUB_OUTPUT
289+
- name: Publish pre-release
290+
if: ${{ contains(github.ref_name, 'rc') || contains(github.ref_name, 'beta') }}
291+
uses: softprops/action-gh-release@v2
292+
with:
293+
prerelease: true
294+
make_latest: false
295+
name: ${{ steps.getReleaseNotes.outputs.RELEASE_NAME }}
296+
files: output/nvda*.exe
297+
body: |
298+
* Highlights can be found in the [release blog post](https://www.nvaccess.org/post/nvda-${{ steps.getReleaseNotes.outputs.NORMALIZED_TAG_NAME }}/).
299+
* [VirusTotal scan results](${{ steps.getVTUrl.outputs.VT_URL }}).
300+
- name: Publish stable release
301+
if: ${{ !contains(github.ref_name, 'rc') && !contains(github.ref_name, 'beta') }}
302+
uses: softprops/action-gh-release@v2
303+
with:
304+
prerelease: false
305+
make_latest: true
306+
discussion_category_name: Releases
307+
name: ${{ steps.getReleaseNotes.outputs.RELEASE_NAME }}
308+
files: output/nvda*.exe
309+
body: |
310+
* Highlights can be found in the [release blog post](https://www.nvaccess.org/post/nvda-${{ steps.getReleaseNotes.outputs.NORMALIZED_TAG_NAME }}/).
311+
* [VirusTotal scan results](${{ steps.getVTUrl.outputs.VT_URL }}).

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ repos:
147147
types_or: [python, c, c++, batch]
148148
- id: licenseCheck
149149
name: Check license compatibility of pip dependencies
150-
files: ^(requirements\.txt|runlicensecheck\.bat)$
150+
files: ^(requirements\.txt|runlicensecheck\.bat|pyproject\.toml)$
151151
entry: ./runlicensecheck.bat
152152
language: script
153153
pass_filenames: false

ci/README.md

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Continuous Integration with GitHub Actions
2+
3+
[Documentation about GitHub Actions](https://docs.github.com/en/actions)
4+
5+
## Builds
6+
7+
Builds will fail if any command has a non-zero exit code.
8+
PowerShell scripts continue on non-terminating errors unless the file is prefixed with `$ErrorActionPreference = "Stop";`.
9+
10+
### Build process
11+
12+
1. Checkout NVDA repository with submodules.
13+
1. Install dependencies (or use cache).
14+
1. Set version and scons variables.
15+
1. Prepare source code.
16+
1. Build launcher.
17+
1. Install NVDA.
18+
1. Prepare for tests.
19+
1. Run tests.
20+
1. Clean up build cache.
21+
1. Release NVDA if this is a tagged release.
22+
23+
## Testing
24+
25+
Before testing we:
26+
27+
* Create directories to store results.
28+
* Install NVDA for system tests
29+
30+
The tests we perform are:
31+
32+
* check translation comments
33+
* license checks
34+
* unit tests
35+
* system tests
36+
37+
## Artifacts
38+
39+
* NVDA launcher.
40+
* Test results.

ci/scripts/installNVDA.ps1

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
$errorCode=0
2+
$nvdaLauncherFile=$(Resolve-Path "$env:nvdaLauncherDir\nvda*.exe")
3+
$nvdaInstallerLogDir=$(Resolve-Path ".\testOutput\install")
4+
$installerLogFilePath="$nvdaInstallerLogDir\nvda_install_temp.log"
5+
$installerCrashDumpPath="$nvdaInstallerLogDir\nvda_crash.dmp"
6+
$installerProcess=Start-Process -FilePath "$nvdaLauncherFile" -ArgumentList "--install-silent --debug-logging --log-file $installerLogFilePath" -passthru
7+
try {
8+
$installerProcess | Wait-Process -Timeout 180 -ErrorAction Stop
9+
$errorCode=$installerProcess.ExitCode
10+
} catch {
11+
Write-Output "NVDA installer process timed out.`n" >> $env:GITHUB_STEP_SUMMARY
12+
$errorCode=1
13+
}
14+
# If the installer failed to exit the log file is still in use.
15+
# We can't/shouldn't upload a file which is locked,
16+
# as a work around create a copy of the log and upload that instead.
17+
Copy-Item -Path $installerLogFilePath -Destination "$nvdaInstallerLogDir\nvda_install.log"
18+
if (Test-Path -Path $installerCrashDumpPath){
19+
Write-Output "NVDA installer process crashed.`n" >> $env:GITHUB_STEP_SUMMARY
20+
$errorCode=1
21+
}
22+
exit $errorCode

0 commit comments

Comments
 (0)