-
Notifications
You must be signed in to change notification settings - Fork 121
Expand file tree
/
Copy pathmrel
More file actions
executable file
·474 lines (402 loc) · 14.2 KB
/
Copy pathmrel
File metadata and controls
executable file
·474 lines (402 loc) · 14.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
#!/usr/bin/env tclsh
#
# MREL, build release files and test them
# Copyright (C) 2020-2025 Xavier Delaruelle
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##########################################################################
proc reportUsage {} {
puts "Usage: $::argv0 \[options\]
Build Modules release files and test them
Options:
-h, --help Show this help message and exit"
}
proc sgr {sgrcode str} {
return "\033\[${sgrcode}m$str\033\[0m"
}
proc logadd {str} {
if {[info exists ::logfid]} {
puts $::logfid $str
}
}
proc reportInfo {str} {
logadd "--- $str"
puts [sgr 2 $str]
}
proc reportError {str} {
logadd "### ERROR: $str"
puts "[sgr {1;31} ERROR]: $str"
}
proc runcmd {args} {
reportInfo "Running command: $args"
eval exec >@$::logfid $args
}
proc ignoreexp {errmsg expmsg} {
if {[string first $expmsg $errmsg] == -1} {
error $errmsg
}
}
proc quitorcont {} {
flush stdout
puts -nonewline "Is this ok \[Y/n\]: "
flush stdout
gets stdin ok
if {$ok ne {} && ![string equal -nocase -length 1 {y} $ok]} {
error Abort
}
}
proc extractflist {relver distcontentfile listfile} {
set fid [open $distcontentfile r]
set distfiles [read $fid]
close $fid
set fid [open $listfile w]
puts $fid [join [lsort [split [string map [list modules-$relver/ {}]\
$distfiles] \n]] \n]
close $fid
}
# parse arguments
set hintmsg "\n Try '$argv0 --help' for more information."
if {$argc > 1} {
reportError "Unexpected number of arguments$hintmsg"
exit 1
} elseif {$argc == 1} {
switch -- [lindex $argv 0] {
-h - --help {
reportUsage
exit 0
}
default {
reportError "Invalid option '[lindex $argv 0]'$hintmsg"
exit 1
}
}
}
# surround whole code to catch error and quit properly
if {[catch {
set exitcode 0
set instdir /tmp/mods+test-install
set rpmbuilddir $env(HOME)/rpmbuild
set srpmdir $rpmbuilddir/SRPMS
set rpmdir $rpmbuilddir/RPMS/$tcl_platform(machine)
set dlurl https://github.com/envmodules/modules/releases/download
set cwd [pwd]
# define and open log file
set logfile mrel.out
set logfid [open $logfile w]
# get current branch
set relbranch [exec git branch --show-current]
if {[regexp {^(main|v\d+.\d+.x)$} $relbranch]} {
reportInfo "Found branch '$relbranch'"
} else {
error "git branch '$relbranch' is not a valid release branch"
}
# ensure head sit on a tag
set reltag [exec git describe --tags --exact-match]
reportInfo "Found release tag '$reltag'"
if {[regexp {^v(\d+.\d+.\d+(-(alpha|beta))?)$} $reltag match relver]} {
reportInfo "Extract release version number '$relver'"
} else {
error "git tag '$reltag' is not a valid release tag"
}
# get previous version for later comparison
set prevtag [exec git describe --tags --abbrev=0 HEAD^]
reportInfo "Found previous release tag '$prevtag'"
if {[regexp {^v(\d+.\d+.\d+(-(alpha|beta))?)$} $prevtag match prevver]} {
reportInfo "Extract previous release version number '$prevver'"
} else {
error "git tag '$prevtag' is not a valid release tag"
}
# acquire credential required to locally install
reportInfo "Running command: sudo --validate"
exec sudo --validate
reportInfo {sudo credential acquired}
# acquire credential to build on remote fedora systems
set fedora_realm FEDORAPROJECT.ORG
if {![info exists env(MREL_FEDORA_USERNAME)]} {
puts -nonewline "$fedora_realm username: "
flush stdout
gets stdin env(MREL_FEDORA_USERNAME)
}
set fedora_princ $env(MREL_FEDORA_USERNAME)@$fedora_realm
reportInfo "Fedora principal set to '$fedora_princ'"
reportInfo "Running command: kinit $fedora_princ"
exec >@stdout kinit $fedora_princ
reportInfo "Kerberos ticket to $fedora_realm realm acquired"
# get name of GitHub remote repository used to trigger CI
if {![info exists env(MREL_GITHUB_TEST_REMOTE)]} {
puts -nonewline "GitHub test remote: "
flush stdout
gets stdin env(MREL_GITHUB_TEST_REMOTE)
}
set gh_test_remote $env(MREL_GITHUB_TEST_REMOTE)
reportInfo "GitHub test remote set to '$gh_test_remote'"
set ghremtgt [lindex [split [exec git remote get-url $gh_test_remote] :.] 2]
set ghstatusurl\
https://api.github.com/repos/$ghremtgt/commits/$relbranch/status
set ghtgturl https://github.com/$ghremtgt/commit/$relbranch
set ghcloneurl https://github.com/$ghremtgt.git
set ghexporturl https://github.com/$ghremtgt/archive/$reltag.tar.gz
# clean previous release files
file delete -force /tmp/mods+test-gz /tmp/mods+test-bz2 /tmp/mods+test-clone\
/tmp/mods+test-export $instdir
file mkdir /tmp/mods+test-gz /tmp/mods+test-bz2 /tmp/mods+test-clone\
/tmp/mods+test-export
reportInfo {Recreate test directory /tmp/mods+test-gz and /tmp/mods+test-bz2\
/tmp/mods+test-clone /tmp/mods+test-export}
foreach oldsrpm [glob -nocomplain $srpmdir/environment-modules-*.src.rpm] {
reportInfo "Delete previous SRPM '$oldsrpm'"
file delete $oldsrpm
}
foreach oldrpm [glob -nocomplain $rpmdir/environment-modules-*.rpm] {
reportInfo "Delete previous RPM '$oldrpm'"
file delete $oldrpm
}
# remove installed RPMs or dist
catch {runcmd 2>@$logfid sudo rpm -e --nodeps scl-utils}
catch {runcmd 2>@$logfid sudo rpm -e --nodeps environment-modules}
catch {runcmd 2>@$logfid sudo rpm -e --nodeps environment-modules-compat}
catch {runcmd 2>@$logfid sudo rpm -e --nodeps Lmod}
runcmd sudo rm -f /usr/share/zsh/site-functions/_ml\
/usr/share/zsh/site-functions/_module /usr/share/zsh/site-functions/ml\
/usr/share/zsh/site-functions/module
runcmd sudo rm -rf /usr/local/Modules
# Phase 1: build dists and verify them
# ---------------------------------------------------------
if {[catch {runcmd make distclean} errmsg]} {
# skip error if things have already been cleaned up
ignoreexp $errmsg {*** Makefile.inc is missing, please run\
'./configure'. Stop.}
}
runcmd ./configure
# download icdiff to compare files
runcmd >&@$logfid make icdiff
# build all dists
runcmd make dist
runcmd make dist-bzip2
runcmd make dist-win
runcmd make srpm
set distgz modules-$relver.tar.gz
set distbz modules-$relver.tar.bz2
set distwin modules-$relver-win.zip
set distgzsum [lindex [exec md5sum $distgz] 0]
set distbzsum [lindex [exec md5sum $distbz] 0]
set distwinsum [lindex [exec md5sum $distwin] 0]
reportInfo "Found dist GZ '$distgz' (size='[file size $distgz]',\
sum='$distgzsum')"
reportInfo "Found dist BZ '$distbz' (size='[file size $distbz]',\
sum='$distbzsum')"
reportInfo "Found dist Win '$distwin' (size='[file size $distwin]',\
sum='$distwinsum')"
# adapt rpm release version in case of non-final release (alpha/beta)
if {[set nonfinalidx [string first - $relver]] != -1} {
set rpmrelver [string range $relver 0 [expr {$nonfinalidx -\
1}]]-0.1.[string range $relver [expr {$nonfinalidx + 1}] end]
} else {
set rpmrelver $relver-1
}
set srcrpm [glob $srpmdir/environment-modules-$rpmrelver.*.src.rpm]
reportInfo "Found source RPM '$srcrpm' (size='[file size $srcrpm]')"
quitorcont
runcmd >log-gz tar tfz $distgz
runcmd >log-bz tar tfj $distbz
runcmd diff -u log-gz log-bz
runcmd >log-win zipinfo -1 $distwin
# prepare current version dist file list to compare to previous dist
extractflist $relver log-gz distfiles
extractflist $relver-win log-win distfiles-win
# fetch previous dists
set prevdistgz modules-$prevver.tar.gz
set prevdistwin modules-$prevver-win.zip
runcmd 2>@$logfid curl -LO $dlurl/$prevtag/$prevdistgz
runcmd 2>@$logfid curl -LO $dlurl/$prevtag/$prevdistwin
# prepare previous version dist file list to compare to previous dist
runcmd >log-prev-gz tar tfz $prevdistgz
extractflist $prevver log-prev-gz distfiles-prev
runcmd >log-prev-win zipinfo -1 $prevdistwin
extractflist $prevver-win log-prev-win distfiles-win-prev
# compare dist content with previous release
runcmd >@stdout ./icdiff distfiles-prev distfiles | less -eFKRX
quitorcont
runcmd >@stdout ./icdiff distfiles-win-prev distfiles-win | less -eFKRX
quitorcont
file delete log-gz log-bz log-win $prevdistgz distfiles distfiles-win\
log-prev-gz distfiles-prev $prevdistwin log-prev-win distfiles-win-prev
# check generated RPM spec file
runcmd >@stdout rpmlint --ignore-unused-rpmlintrc --rpmlintrc\
share/rpm/environment-modules.rpmlintrc share/rpm/environment-modules.spec\
$srcrpm
quitorcont
# Phase 2: push to CI
# ---------------------------------------------------------
runcmd 2>@$logfid git push --force $gh_test_remote c-3.2
runcmd 2>@$logfid git push --force $gh_test_remote $relbranch
runcmd 2>@$logfid git push --force $gh_test_remote $reltag
# see Phase 6 for CI result check
# Phase 3: build, test, install from RPM built locally
# ---------------------------------------------------------
# extend sudo timeout for next usages
exec sudo --validate
runcmd 2>@$logfid rpmbuild --rebuild $srcrpm
set rpmpkg_list [glob $rpmdir/environment-modules-$rpmrelver.*.rpm]
foreach rpmpkg $rpmpkg_list {
runcmd >@stdout rpm -qlp $rpmpkg | less -eFKRX
quitorcont
# check installation of built RPM
runcmd sudo rpm -ivh $rpmpkg
}
# check all RPM files (spec, srpm, rpms) all at once to check rpm files and
# see if rpmlint produces some unused-rpmlintrc warnings
runcmd >@stdout rpmlint --rpmlintrc share/rpm/environment-modules.rpmlintrc\
share/rpm/environment-modules.spec $srcrpm {*}$rpmpkg_list
quitorcont
# test RPM uninstall
runcmd 2>@$logfid sudo rpm -e --nodeps environment-modules
# Phase 4: build, test, install from generated dists
# ---------------------------------------------------------
cd /tmp/mods+test-gz
runcmd tar xfz $cwd/$distgz
cd modules-$relver
reportInfo "Moved into '[pwd]' directory"
runcmd ./configure --prefix=$instdir
runcmd make
runcmd 2>@$logfid script/mt
runcmd 2>@$logfid make install
runcmd script/mt install
runcmd 2>@$logfid make uninstall
runcmd make clean
cd /tmp/mods+test-bz2
runcmd tar xfj $cwd/$distbz
cd modules-$relver
reportInfo "Moved into '[pwd]' directory"
runcmd ./configure --prefix=$instdir
runcmd make
runcmd 2>@$logfid script/mt
runcmd 2>@$logfid make install
runcmd script/mt install
runcmd 2>@$logfid make uninstall
runcmd make clean
cd /tmp/mods+test-clone
runcmd 2>@$logfid git clone $ghcloneurl
cd modules
reportInfo "Moved into '[pwd]' directory"
runcmd 2>@$logfid git checkout $relbranch
runcmd 2>@$logfid ./configure --prefix=$instdir
runcmd make
runcmd 2>@$logfid script/mt quick
runcmd 2>@$logfid make install
runcmd script/mt install
runcmd 2>@$logfid make uninstall
runcmd make clean
cd /tmp/mods+test-export
runcmd 2>@$logfid curl -LO $ghexporturl
runcmd tar xfz $reltag.tar.gz
cd modules-$relver
reportInfo "Moved into '[pwd]' directory"
runcmd ./configure --prefix=$instdir
runcmd make
runcmd 2>@$logfid script/mt quick
runcmd 2>@$logfid make install
runcmd script/mt install
runcmd 2>@$logfid make uninstall
runcmd make clean
cd $cwd
reportInfo "Moved back into '[pwd]' directory"
# Phase 5: build and test on Fedora platform
# ---------------------------------------------------------
# get list of targets
set koji_out [exec koji list-targets --quiet]
foreach {match ftarget} [regexp -all -inline -line {^(f\d+|epel\d+) }\
$koji_out] {
lappend fedora_target_list $ftarget
}
reportInfo "Use Fedora targets: $fedora_target_list"
# submit builds
foreach ftarget $fedora_target_list {
set koji_out [exec koji build --scratch $ftarget $srcrpm --nowait\
--noprogress]
if {[regexp {Created task: (\d+)} $koji_out match taskid]} {
reportInfo "Submitted task '$taskid' on '$ftarget' target"
} else {
error "cannot find koji task submitted to $ftarget"
}
set koji_tasks($taskid) $ftarget
}
# monitor build completeness
set koji_taskinfo_url https://koji.fedoraproject.org/koji/taskinfo?taskID=
while {[array size koji_tasks]} {
foreach ktask [array names koji_tasks] {
if {[catch {
set koji_out [exec koji taskinfo $ktask]
regexp {State: (\w+)} $koji_out match kstate
switch -- $kstate {
free - open - assigned {
reportInfo "Task '$ktask' on '$koji_tasks($ktask)' still\
running"
}
closed {
reportInfo "Task '$ktask' on '$koji_tasks($ktask)'\
successfully completed"
unset koji_tasks($ktask)
}
default {
reportError "Task '$ktask' on '$koji_tasks($ktask)' failed:\
\n$koji_out\nSee $koji_taskinfo_url$ktask"
unset koji_tasks($ktask)
set exitcode 1
}
}
} errmsg]} {
# allow for 1 failure
if {[info exists koji_fail($ktask)]} {
error $errmsg
} else {
reportInfo "Cannot fetch state of task '$ktask' on\
'$koji_tasks($ktask)', will be retried"
set koji_fail($ktask) 1
}
# clear previous failure if it succeed this time
} elseif {[info exists koji_fail($ktask)]} {
unset koji_fail($ktask)
}
}
# wait 30 seconds before next check loop
if {[array size koji_tasks]} {
after 30000
}
}
# Phase 6: verify CI result
# ---------------------------------------------------------
reportInfo "Checking CI tests status on $ghstatusurl"
while {[set cistatus [lindex [split [string range [exec curl -s $ghstatusurl]\
0 30] \"] 3]] eq {pending}} {
reportInfo "CI tests still in progress"
# wait 30 seconds before next check loop
after 30000
}
if {$cistatus eq {success}} {
reportInfo "CI tests are successful, see $ghtgturl"
} else {
reportError "CI tests have failed, see $ghtgturl"
set exitcode 1
}
# green light for mpub
exec >mpub.ok md5sum $distgz $distbz $distwin
# exit in error if any occurred
} errmsg]} {
reportError $errmsg
set exitcode 1
}
close $logfid
exit $exitcode
# vim:set tabstop=3 shiftwidth=3 expandtab autoindent syntax=tcl: