1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2016-2021 Edgewall Software
4 # Copyright (C) 2016 Christian Boos <cboos@edgewall.org>
5 # All rights reserved.
6 #
7 # This software is licensed as described in the file COPYING, which
8 # you should have received as part of this distribution. The terms
9 # are also available at https://trac.edgewall.com/license.html.
10 #
11 # This software consists of voluntary contributions made by many
12 # individuals. For the exact contribution history, see the revision
13 # history and logs, available at https://trac.edgewall.org/.
14
15 # ------------------------------------------------------------------
16 # This is a PowerShell script implementing the build steps used by
17 # the AppVeyor Continuous Delivery service for Windows, Trac project.
18 #
19 # The builds results are published at:
20 #
21 # https://ci.appveyor.com/project/edgewall/trac
22 #
23 # or, for Git topic branches pushed on GitHub forks, at:
24 #
25 # https://ci.appveyor.com/project/<developer-user-id>/trac
26 #
27 # ------------------------------------------------------------------
28
29 # ------------------------------------------------------------------
30 # Settings
31 # ------------------------------------------------------------------
32
33 # Update the following variables to match the current build
34 # environment on AppVeyor.
35 #
36 # See in particular:
37 # - https://www.appveyor.com/docs/installed-software#python
38 # - https://www.appveyor.com/docs/installed-software#mingw-msys-cygwin
39 # - https://www.appveyor.com/docs/services-databases#mysql
40 # - https://www.appveyor.com/docs/services-databases#postgresql
41
42 $msysHome = 'C:\msys64\usr\bin'
43 $deps = 'C:\projects\dependencies'
44
45 $mysqlHome = 'C:\Program Files\MySql\MySQL Server 5.7'
46 $mysqlPwd = 'Password12!'
47
48 $pgHome = 'C:\Program Files\PostgreSQL\9.3'
49 $pgUser = 'postgres'
50 $pgPassword = 'Password12!'
51
52 $firefoxHome = 'C:\Program Files\Mozilla Firefox'
53
54 # External Python dependencies
55
56 $pipPackages = @(
57 'setuptools',
58 'jinja2',
59 'babel',
60 'docutils',
61 'passlib',
62 'pygments',
63 'pytz',
64 'textile',
65 'wheel',
66 'selenium'
67 )
68
69 $condaPackages = @(
70 'lxml'
71 )
72
73 $svnBase = "svn-win32-1.8.15"
74 $svnBaseAp = "$svnBase-ap24"
75 $svnUrlBase = "https://sourceforge.net/projects/win32svn/files/1.8.15/apache24"
76
77 # ------------------------------------------------------------------
78 # "Environment" environment variables
79 # ------------------------------------------------------------------
80
81 # In the build matrix, we can set arbitrary environment variables
82 # which together define the software configuration that will be
83 # tested.
84
85 # These variables are:
86 # - PYTHONHOME: the version of python we are testing
87 # - TRAC_TEST_DB_URI: the database backend we are testing
88 # - SKIP_ENV: don't perform any step with this environment (optional)
89 # - SKIP_BUILD: don't execute the Build step for this environment (optional)
90 # - SKIP_TESTS: don't execute the Tests step for this environment (optional)
91 #
92 # Note that any combination should work, except for MySQL which can
93 # only be installed conveniently from a Conda version of Python.
94
95 # "Aliases"
96
97 $pyHome = $env:PYTHONHOME
98 $usingMysql = $env:TRAC_TEST_DB_URI -match '^mysql:'
99 $usingPostgresql = $env:TRAC_TEST_DB_URI -match '^postgres:'
100 $usingFirefox = $pipPackages -contains 'selenium'
101 $skipInstall = [bool]$env:SKIP_ENV
102 $skipBuild = $env:SKIP_BUILD -or $env:SKIP_ENV
103 $skipTests = $env:SKIP_TESTS -or $env:SKIP_ENV
104
105
106 # ------------------------------------------------------------------
107 # Utilities
108 # ------------------------------------------------------------------
109
110 # Documentation for AppVeyor API (Add-AppveyorMessage, etc.) can be
111 # found at: https://www.appveyor.com/docs/build-worker-api
112
Write-Step([string]$name, [bool]$skip)113 function Write-Step([string]$name, [bool]$skip) {
114 if ($skip) {
115 $message = "Skipping step $name"
116 Write-Host $message
117 Add-AppveyorMessage -Message $message
118 }
119 else {
120 Write-Host @"
121
122 ------------------------------------------------------------------
123 $name
124 ------------------------------------------------------------------
125 "@
126 }
127 }
128
129 # Make it easier to run the tests locally, for debugging.
130 #
131 # Note that for this you may need to enable sourcing local scripts,
132 # from your PowerShell console:
133 #
134 # Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process
135 #
136 # . .\contrib\appveyor.ps1
137 #
138 # See https://trac.edgewall.org/wiki/AppVeyor for additional info.
139
140 if (-not $env:APPVEYOR) {
Debug-Callernull141 function Debug-Caller {
142 $caller = (Get-Variable MyInvocation -Scope 1).Value.MyCommand.Name
143 Write-Debug "$caller $args"
144 }
Add-AppveyorMessage()145 function Add-AppveyorMessage() { Debug-Caller @args }
Add-AppveyorTest()146 function Add-AppveyorTest() { Debug-Caller @args }
Update-AppveyorTest()147 function Update-AppveyorTest() { Debug-Caller @args }
Push-AppveyorArtifact()148 function Push-AppveyorArtifact() { Debug-Caller @args }
149 }
150
151
152 # ------------------------------------------------------------------
153 # Prologue
154 # ------------------------------------------------------------------
155
156 # Actions common to all steps (set up the PATH, determine Python version...)
157
158 $pyV = [string](& python.exe -c 'import sys; print sys.version' 2>&1)
159 $pyVersion = if ($pyV -match '^(\d\.\d)') { $Matches[1] }
160 $py64 = ($pyV -match '64 bit')
161 $pyIsConda = $pyV -match 'Continuum Analytics'
162
163 # ------------------------------------------------------------------
164 # Steps
165 # ------------------------------------------------------------------
166
Trac-Install()167 function Trac-Install {
168
169 $env:Path = "$pyHome;$pyHome\Scripts;$pyHome\Library\bin;$msysHome;$($env:Path)"
170
171 # Subversion support
172 if (-not $py64) {
173 $env:Path = "$deps\$svnBase\bin;$($env:Path)"
174 $env:PYTHONPATH = "$deps\$pyVersion\$svnBase\python;$($env:PYTHONPATH)"
175 }
176
177 if ($usingFirefox) {
178 $env:Path = "$($env:Path);$firefoxHome"
179 }
180
181 Write-Step -Name INSTALL -Skip $skipInstall
182
183 if ($skipInstall) {
184 return
185 }
186
187 if (-not (Test-Path $deps)) {
188 & mkdir $deps
189 }
190
191 # Subversion support via win32svn project, for Python 2.7 32-bits
192
193 if (-not $py64) {
194 $svnBinariesZip = "$deps\$svnBaseAp.zip"
195 if (-not (Test-Path $svnBinariesZip)) {
196 & curl.exe -Ss -L -o $svnBinariesZip `
197 "$svnUrlBase/$svnBaseAp.zip/download"
198 & unzip.exe $svnBinariesZip -d $deps
199 }
200
201 $svnPython = "$($svnBaseAp)_py$($pyVersion -replace '\.', '')"
202 $svnPythonZip = "$deps\$svnPython.zip"
203 if (-not (Test-Path $svnPythonZip)) {
204 & curl.exe -Ss -L -o $svnPythonZip `
205 "$svnUrlBase/$svnPython.zip/download"
206 & mkdir "$deps\$pyVersion"
207 & unzip $svnPythonZip -d "$deps\$pyVersion"
208 }
209 }
210
211 # Install packages via pip
212
213 & python.exe -m pip install -U pip
214 & pip.exe --version
215 & pip.exe install -U $pipPackages
216
217 if ($pyIsConda) {
218 & conda.exe install -qy $condaPackages
219 }
220
221 if ($usingMysql) {
222 #
223 # $TRAC_TEST_DB_URI="mysql://tracuser:password@localhost/trac"
224 #
225
226 # Conda provides PyMySQL support for Windows (x86 and x64)
227
228 & conda.exe install -qy pymysql
229
230 Add-AppveyorMessage -Message "1.1. pymysql package installed" `
231 -Category Information
232 }
233 elseif ($usingPostgresql) {
234 #
235 # $TRAC_TEST_DB_URI=
236 # "postgres://tracuser:password@localhost/trac?schema=tractest"
237 #
238
239 & pip.exe install psycopg2
240
241 Add-AppveyorMessage -Message "1.1. psycopg2 package installed" `
242 -Category Information
243 }
244
245 if ($usingFirefox) {
246 & cinst.exe --no-progress firefox
247 }
248
249 & pip.exe list --format=columns
250
251 # Prepare local Makefile.cfg
252
253 ".uri = $env:TRAC_TEST_DB_URI" | Out-File -Encoding ASCII 'Makefile.cfg'
254
255 # Note 1: echo would create an UCS-2 file with a BOM, make.exe
256 # doesn't appreciate...
257
258 # Note 2: we can't do more at this stage, as the services
259 # (MySQL/PostgreSQL) are not started yet.
260 }
261
262
263
Trac-Buildnull264 function Trac-Build {
265
266 Write-Step -Name BUILD -Skip $skipBuild
267
268 if ($skipBuild) {
269 return
270 }
271
272 # Preparing database if needed
273
274 if ($usingMysql) {
275 #
276 # $TRAC_TEST_DB_URI="mysql://tracuser:password@localhost/trac"
277 #
278 $env:MYSQL_PWD = $mysqlPwd
279 $env:Path = "$mysqlHome\bin;$($env:Path)"
280
281 Write-Host "Creating 'trac' MySQL database with user 'tracuser'"
282
283 & mysql.exe -u root -e `
284 ('CREATE DATABASE trac DEFAULT CHARACTER SET utf8mb4' +
285 ' COLLATE utf8mb4_bin')
286 & mysql.exe -u root -e `
287 'CREATE USER tracuser@localhost IDENTIFIED BY ''password'';'
288 & mysql.exe -u root -e `
289 'GRANT ALL ON trac.* TO tracuser@localhost; FLUSH PRIVILEGES;'
290
291 Add-AppveyorMessage -Message "2.1. MySQL database created" `
292 -Category Information
293 }
294 elseif ($usingPostgresql) {
295 #
296 # $TRAC_TEST_DB_URI=
297 # "postgres://tracuser:password@localhost/trac?schema=tractest"
298 #
299 $env:PGUSER = $pgUser
300 $env:PGPASSWORD = $pgPassword
301 $env:Path = "$pgHome\bin;$($env:Path)"
302
303 Write-Host "Creating 'trac' PostgreSQL database with user 'tracuser'"
304
305 & psql.exe -U postgres -c `
306 ('CREATE USER tracuser NOSUPERUSER NOCREATEDB CREATEROLE' +
307 ' PASSWORD ''password'';')
308 & psql.exe -U postgres -c `
309 'CREATE DATABASE trac OWNER tracuser;'
310
311 Add-AppveyorMessage -Message "2.1. PostgreSQL database created" `
312 -Category Information
313 }
314
315 Write-Host "make compile"
316
317 # compile: if there are fuzzy catalogs, an error message will be
318 # generated on stderr.
319
320 & make.exe Trac.egg-info compile 2>&1 | Tee-Object -Variable make
321
322 $stderr = $make | ?{ $_ -is [System.Management.Automation.ErrorRecord] }
323 $stdout = $make | ?{ $_ -isnot [System.Management.Automation.ErrorRecord] }
324
325 if ($LastExitCode) {
326 Add-AppveyorMessage -Message "2.2. make compile produced errors" `
327 -Category Error -Details ($stderr -join "`n")
328 }
329 elseif ($stderr) {
330 Add-AppveyorMessage -Message "2.2. make compile produced warnings" `
331 -Category Warning -Details ($stderr -join "`n")
332 }
333 else {
334 Add-AppveyorMessage -Message "2.2. make compile was successful" `
335 -Category Information
336 }
337 }
338
339
340
Trac-Tests()341 function Trac-Tests {
342
343 Write-Step -Name TESTS -Skip $skipTests
344
345 $config = "$pyHome - $env:TRAC_TEST_DB_URI"
346
347 if ("$env:TRAC_TEST_DB_URI" -eq '') {
348 $config += 'sqlite :memory:'
349 }
350
351 function Make-Test([string]$goal, [string]$name, [ref]$code) {
352 if ($skipTests) {
353 Add-AppveyorTest -Name $name -Outcome Skipped
354 return
355 }
356
357 Write-Host "make $goal"
358
359 Add-AppveyorTest -Name $name -Outcome Running
360 # Enable verbose output to avoid appearance of hanging job on appveyor
361 & make.exe testopts=-v $goal 2>&1 | Tee-Object -Variable make
362
363 # Determine outcome Passed or Failed
364 $outcome = 'Passed'
365 if ($LastExitCode) {
366 $outcome = 'Failed'
367 $code.value += 1
368 }
369
370 $stderr = $make |
371 ?{ $_ -is [System.Management.Automation.ErrorRecord] }
372 $stdout = $make |
373 ?{ $_ -isnot [System.Management.Automation.ErrorRecord] }
374
375 # Retrieve duration of the tests
376
377 $msecs = 0
378 if ([string]$stderr -match "Ran \d+ tests in (\d+\.\d+)s") {
379 $secs = $matches[1]
380 $msecs = [math]::Round([float]$secs * 1000)
381 }
382
383 Update-AppveyorTest -Name $name -Outcome $outcome `
384 -StdOut ($stdout -join "`n") -StdErr ($stderr -join '') `
385 -Duration $msecs
386 }
387
388 $exit = $fexit = 0
389
390 #
391 # Running unit-tests
392 #
393
394 Make-Test -Goal unit-test -Name "Unit tests for $config" `
395 -Code ([ref]$exit)
396
397 #
398 # Running functional tests
399 #
400
401 Make-Test -Goal functional-test -Name "Functional tests for $config" `
402 -Code ([ref]$fexit)
403
404 if (-not $fexit -eq 0) {
405 Write-Host "Saving functional logs in testenv.zip"
406 & 7z.exe a testenv.zip testenv
407
408 Push-AppveyorArtifact testenv.zip
409
410 $exit = $fexit
411 }
412
413 if (-not $exit -eq 0) {
414 Write-Host "Exiting with code $exit"
415 Exit $exit
416 }
417
418 if (-not $skipTests) {
419 Write-Host "All tests passed."
420 }
421
422 #
423 # Prepare release artifacts
424 #
425
426 & make.exe release-src wininst
427 }
428