OILS / regtest / aports-html.sh View on Github | oils.pub

816 lines, 374 significant
1#!/usr/bin/env bash
2#
3# Make HTML reports
4#
5# Usage:
6# regtest/aports-html.sh <function name>
7#
8# Examples:
9# $0 sync-results he.oils.pub
10# $0 write-all-reports
11# $0 make-wwz _tmp/aports-report/2025-08-03
12# $0 deploy-wwz-op _tmp/aports-report/2025-08-03.wwz # deploy to op.oils.pub
13
14: ${LIB_OSH=stdlib/osh}
15source $LIB_OSH/bash-strict.sh
16source $LIB_OSH/task-five.sh
17
18source regtest/aports-common.sh
19
20REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
21source test/tsv-lib.sh # tsv2html3
22source web/table/html.sh # table-sort-{begin,end}
23source benchmarks/common.sh # cmark
24source build/dev-shell.sh # python2
25
26sqlite-tabs-headers() {
27 sqlite3 \
28 -cmd '.mode tabs' \
29 -cmd '.headers on' \
30 "$@"
31}
32
33html-head() {
34 # python3 because we're outside containers
35 PYTHONPATH=. python3 doctools/html_head.py "$@"
36}
37
38index-html() {
39 local base_url='../../../../web'
40 html-head --title "aports Build" \
41 "$base_url/base.css"
42
43 # TODO:
44 # - Stats for each config:
45 # - number of non-zero exit codes, total packages
46
47 cmark <<'EOF'
48<body class="width35">
49
50<p id="home-link">
51 <a href="/">Home</a>
52</p>
53
54# aports Build
55
56Configurations:
57
58- [baseline](baseline/packages.html) - [raw tasks](baseline/tasks.html) - [metrics](baseline/metrics.txt)
59- [osh-as-sh](osh-as-sh/packages.html) - [raw tasks](osh-as-sh/tasks.html) - [metrics](osh-as-sh/metrics.txt)
60
61## Baseline versus osh-as-sh
62
63- [diff_baseline](diff_baseline.html)
64
65## osh-as-sh versus osh-as-bash
66
67TODO
68
69</body>
70EOF
71}
72
73diff-metrics-html() {
74 local db=${1:-_tmp/aports-report/2025-08-03/diff_merged.db}
75
76 sqlite3 $db < regtest/aports/summary.sql
77}
78
79table-page-html() {
80 local base_dir=${1:-$REPORT_DIR/$EPOCH}
81 local name=${2:-diff_baseline}
82 local base_url=${3:-'../../../../web'}
83 local title=${4:-'OSH Disagreements - regtest/aports'}
84
85 html-head --title "$title" \
86 "$base_url/ajax.js" \
87 "$base_url/table/table-sort.js" \
88 "$base_url/table/table-sort.css" \
89 "$base_url/base.css"
90
91 table-sort-begin 'width60'
92
93 cmark <<EOF
94<p id="home-link">
95 <a href="../index.html">Up</a> |
96 <a href="/">Home</a>
97</p>
98
99# $title
100
101EOF
102
103 tsv2html3 $base_dir/$name.tsv
104
105 cmark <<EOF
106
107[$name.tsv]($name.tsv)
108EOF
109
110 table-sort-end "$name" # ID for sorting
111}
112
113merge-diff-html() {
114 local base_dir=${1:-$REPORT_DIR/$EPOCH}
115 local base_url=${2:-'../../../../web'}
116 local title=${3:-'OSH Disagreements - regtest/aports'}
117
118 html-head --title "$title" \
119 "$base_url/ajax.js" \
120 "$base_url/table/table-sort.js" \
121 "$base_url/table/table-sort.css" \
122 "$base_url/base.css"
123
124 table-sort-begin 'width60' # <body> <p>
125
126 cmark <<EOF
127<p id="home-link">
128 <a href="../index.html">Up</a> |
129 <a href="/">Home</a>
130</p>
131
132# $title
133
134EOF
135
136 diff-metrics-html $base_dir/diff_merged.db
137
138 cmark << 'EOF'
139[tree](tree.html) &nbsp;&nbsp; [metrics](metrics.html) &nbsp;&nbsp; [disagree-packages.txt](disagree-packages.txt)
140
141## Notable Disagreements
142
143<div style="color: #666;">
144
145(Hint: **click** on the cause column header to sort)
146
147</div>
148
149EOF
150
151 local name=notable_disagree
152 tsv2html3 $base_dir/$name.tsv
153
154 cmark <<EOF
155
156[$name.tsv]($name.tsv)
157
158## Baseline-Only Failures
159EOF
160
161 name=baseline_only
162 table-sort-begin 'width60'
163 tsv2html3 $base_dir/$name.tsv
164
165 cmark <<EOF
166[$name.tsv]($name.tsv)
167
168## Other Failures
169EOF
170
171 name=other_fail
172 table-sort-begin 'width60'
173 tsv2html3 $base_dir/$name.tsv
174
175 cmark <<EOF
176
177[$name.tsv]($name.tsv)
178
179## Timeouts
180EOF
181
182 name=timeout
183 table-sort-begin 'width60'
184 tsv2html3 $base_dir/$name.tsv
185
186 cmark <<EOF
187
188[$name.tsv]($name.tsv)
189EOF
190
191 # Sort these 3 tables
192 table-sort-end-many notable_disagree baseline_only other_fail timeout
193}
194
195tasks-html() {
196 local tsv=$1
197 # note: escaping problems with title
198 # it gets interpolated into markdown and html
199 local title=$2
200
201 local base_url='../../../../../web'
202 html-head --title "$title" \
203 "$base_url/ajax.js" \
204 "$base_url/table/table-sort.js" \
205 "$base_url/table/table-sort.css" \
206 "$base_url/base.css"
207
208 table-sort-begin 'width60'
209
210 cmark <<EOF
211<p id="home-link">
212 <a href="../index.html">Up</a> |
213 <a href="/">Home</a>
214</p>
215
216# $title
217EOF
218
219 tsv2html3 $tsv
220
221 local id=$(basename $tsv .tsv)
222 cmark <<EOF
223
224[$id.tsv]($id.tsv)
225EOF
226
227 table-sort-end "$id" # ID for sorting
228}
229
230published-html() {
231 local base_url='../../web'
232
233 local title='regtest/aports'
234
235 html-head --title "$title" \
236 "$base_url/base.css"
237
238 echo '
239 <body class="width35">
240 <style>
241 code { color: green; }
242 </style>
243
244 <p id="home-link">
245 <a href="/">Home</a> |
246 <a href="https://oils.pub/">oils.pub</a>
247 </p>
248 '
249
250 { echo "## $title"
251 echo '
252Testing OSH on decades worth of shell scripts. [Source code](https://github.com/oils-for-unix/oils/tree/master/regtest).
253
254The `aports/main` repo has 1595 `APKBUILD` files, and `aports/community` has
2557168. A disagreement is when the package succeeds normally, but fails when
256`osh` becomes the system shell. Caveats: timeouts and flakiness.
257
258### main
259
260- [2025-08-07-fix](2025-08-07-fix.wwz/_tmp/aports-report/2025-08-07-fix/diff_merged.html) - **131** disagreements
261- [2025-08-14-fix](2025-08-14-fix.wwz/_tmp/aports-report/2025-08-14-fix/diff_merged.html)
262- [2025-08-26-ifs](2025-08-26-ifs.wwz/_tmp/aports-report/2025-08-26-ifs/diff_merged.html) - **62** after `IFS` fix
263 - new causes: [2025-09-06-edit](2025-09-06-edit.wwz/_tmp/aports-report/2025-09-06-edit/diff_merged.html)
264- [2025-09-07](2025-09-07.wwz/_tmp/aports-report/2025-09-07/diff_merged.html)
265- [2025-09-08](2025-09-08.wwz/_tmp/aports-report/2025-09-08/diff_merged.html)
266 - [2025-09-08-edit](2025-09-08-edit.wwz/_tmp/aports-report/2025-09-08-edit/diff_merged.html)
267 - [2025-09-08-notable](2025-09-08-notable.wwz/_tmp/aports-report/2025-09-08-notable/diff_merged.html)
268- [2025-09-10-overlayfs](2025-09-10-overlayfs.wwz/_tmp/aports-report/2025-09-10-overlayfs/diff_merged.html)
269- [2025-09-11-match](2025-09-11-match.wwz/_tmp/aports-report/2025-09-11-match/diff_merged.html)
270- [2025-09-15-order](2025-09-15-order.wwz/_tmp/aports-report/2025-09-15-order/diff_merged.html) - **32** disagreements with `osh` as `/bin/sh`
271
272After this success, we expanded our testing:
273
274- [2025-09-17-ash2](2025-09-17-ash2.wwz/_tmp/aports-report/2025-09-17-ash2/diff_merged.html) - **37**, after adding `osh` as `/bin/ash`
275- [2025-09-18-bash](2025-09-18-bash.wwz/_tmp/aports-report/2025-09-18-bash/diff_merged.html) - **43**, after adding `osh` as `/bin/bash`
276 - only run on packages that disagree: [2025-09-27-disagree](2025-09-27-disagree.wwz/_tmp/aports-report/2025-09-27-disagree/diff_merged.html)
277 - new causes: [2025-10-03-causes](2025-10-03-causes.wwz/_tmp/aports-report/2025-10-03-causes/diff_merged.html)
278- [2025-10-15-main](2025-10-15-main.wwz/_tmp/aports-report/2025-10-15-main/diff_merged.html) - **38** disagreements
279 - [2025-10-16](2025-10-16.wwz/_tmp/aports-report/2025-10-16/diff_merged.html) - down to **35** after `x=1>` and `cd x y` fixes
280 - [2025-10-22](2025-10-22.wwz/_tmp/aports-report/2025-10-22/diff_merged.html) - down to **24** after `((` and `$(false)` fixes
281 - [2025-10-26-cause](2025-10-26-cause.wwz/_tmp/aports-report/2025-10-26-cause/diff_merged.html) - updated causes
282 - [2025-11-01-main-cause](2025-11-01-main-cause.wwz/_tmp/aports-report/2025-11-01-main-cause/diff_merged.html) - updated causes
283 - [2025-11-01-main-again](2025-11-01-main-again.wwz/_tmp/aports-report/2025-11-01-main-again/diff_merged.html) - down to **18**
284 - [2025-11-02-main-patch](2025-11-02-main-patch.wwz/_tmp/aports-report/2025-11-02-main-patch/diff_merged.html) - down to **14**
285
286### community
287
288- [2025-10-08-comm](2025-10-08-comm.wwz/_tmp/aports-report/2025-10-08-comm/diff_merged.html) - **86** disagreements
289 - [2025-10-16-comm-disagree](2025-10-16-comm-disagree.wwz/_tmp/aports-report/2025-10-16-comm-disagree/diff_merged.html) - **71** disagreements
290 - [2025-10-22-comm](2025-10-22-comm.wwz/_tmp/aports-report/2025-10-22-comm/diff_merged.html) - down to **65** after `((` and `$(false)` fixes
291 - [2025-10-26-comm-cause](2025-10-26-comm-cause.wwz/_tmp/aports-report/2025-10-26-comm-cause/diff_merged.html) - updated causes
292 - [2025-11-01-comm-cause](2025-11-01-comm-cause.wwz/_tmp/aports-report/2025-11-01-comm-cause/diff_merged.html) - updated causes
293
294';
295 } | cmark
296
297 echo '
298 </body>
299</html>
300'
301}
302
303typed-tsv-to-sql() {
304 local tsv=${1:-$BASE_DIR/big/tasks.tsv}
305 local name
306 name=${2:-$(basename $tsv .tsv)}
307
308 local schema="${tsv%'.tsv'}.schema.tsv"
309 #echo $name $schema
310
311 echo "CREATE TABLE $name ("
312 web/table/schema2sqlite.py $schema
313 echo ');'
314
315 echo "
316-- use this temp import because we already created the table, and
317-- '.headers on' is not expected in that case
318
319.import $tsv temp_import
320insert into $name select * from temp_import;
321drop table temp_import;
322
323-- select * from $name limit 5;
324 "
325}
326
327my-rsync() {
328 #rsync --archive --verbose --dry-run "$@"
329 rsync --archive --verbose "$@"
330}
331
332readonly EPOCH=${EPOCH:-'2025-07-28-100'}
333readonly BUILD_HOST=he.oils.pub
334#readonly BUILD_HOST=lenny.local
335
336sync-results() {
337 local host=${1:-$BUILD_HOST}
338 local prefix=${2:-}
339 mkdir -p $REPORT_DIR
340
341 # Exclude .apk files, because they are large. We only need the metadata
342 my-rsync \
343 --exclude '*.apk' \
344 "$host:~/git/oils-for-unix/oils/_tmp/aports-build/$prefix*" \
345 $REPORT_DIR/
346}
347
348local-sync() {
349 mkdir -p $REPORT_DIR
350
351 #my-rsync --dry-run $BASE_DIR/ $REPORT_DIR/
352 my-rsync $BASE_DIR/ $REPORT_DIR/
353}
354
355make-package-table() {
356 local base_dir=${1:-$REPORT_DIR/$EPOCH}
357 local config=${2:-baseline}
358
359 local db=$PWD/$base_dir/$config/tables.db
360 rm -f $db
361
362 typed-tsv-to-sql $base_dir/$config/tasks.tsv | sqlite-tabs-headers $db
363
364 sqlite3 -cmd '.mode columns' $db < regtest/aports/tasks.sql
365
366 pushd $base_dir/$config > /dev/null
367
368 db-to-tsv $db packages
369
370 # Set precision
371 echo "
372 alter table packages_schema add column precision;
373
374 update packages_schema set precision = 1 where column_name = 'elapsed_secs';
375 update packages_schema set precision = 1 where column_name = 'user_elapsed_ratio';
376 update packages_schema set precision = 1 where column_name = 'user_sys_ratio';
377 update packages_schema set precision = 1 where column_name = 'max_rss_MB';
378 " | sqlite3 $db
379
380 # Count .apk for this config
381 # Note: we could also create an 'apk' table, in addition to 'packages', and diff
382 # But that's a bunch of overhead
383
384 local num_apk
385 num_apk=$(cat apk.txt | wc -l)
386
387 sqlite3 $db >metrics.txt <<EOF
388update metrics
389set num_apk = $num_apk
390where id = 1;
391
392.mode column
393select * from metrics;
394EOF
395
396 popd > /dev/null
397
398 #cat $base_dir/$config/packages.schema.tsv
399}
400
401tasks-schema() {
402 here-schema-tsv-4col <<EOF
403column_name type precision strftime
404status integer 0 -
405elapsed_secs float 1 -
406start_time float 1 %H:%M:%S
407end_time float 1 %H:%M:%S
408user_secs float 1 -
409sys_secs float 1 -
410max_rss_KiB integer 0 -
411xargs_slot integer 0 -
412pkg string 0 -
413pkg_HREF string 0 -
414EOF
415}
416
417write-tables-for-config() {
418 local base_dir=${1:-$REPORT_DIR/$EPOCH}
419 local config=${2:-baseline}
420
421 local tasks_tsv=$base_dir/$config/tasks.tsv
422 mkdir -p $base_dir/$config
423
424 tasks-schema >$base_dir/$config/tasks.schema.tsv
425
426 local out=$base_dir/$config/tasks.html
427 tasks-html $tasks_tsv "tasks: $config" > $out
428 log "Wrote $out"
429
430 make-package-table "$base_dir" "$config"
431
432 local packages_tsv=$base_dir/$config/packages.tsv
433
434 local out=$base_dir/$config/packages.html
435 tasks-html $packages_tsv "packages: $config" > $out
436 log "Wrote $out"
437}
438
439make-diff-db() {
440 local base_dir=$1
441 local name=${2:-diff_baseline}
442
443 local db=$name.db
444
445 local diff_sql=$PWD/regtest/aports/diff.sql
446 local cause_awk=$PWD/regtest/aports/cause.awk
447 local cause_sql=$PWD/regtest/aports/cause.sql
448
449 pushd $base_dir > /dev/null
450
451 rm -f $db
452 sqlite3 $db < $diff_sql
453
454 #
455 # Now make diffs
456 #
457
458 sqlite3 $db >failed-packages.txt <<EOF
459.mode tabs
460-- this is a text file, so headers are OFF
461.headers off
462
463select pkg from diff_baseline;
464EOF
465
466 mkdir -p error
467 cat failed-packages.txt | while read -r pkg; do
468 #local left=baseline/log/$pkg.log.txt
469 local right=osh-as-sh/log/$pkg.log.txt
470
471 # lower case 'error fail' are more noisy, e.g. command line flags
472 egrep 'Error|ERROR|Fail|FAIL|test-suite.log' $right > error/$pkg.txt || true
473 done
474
475 { echo "pkg${TAB}cause${TAB}suite${TAB}suite_HREF"
476 cat failed-packages.txt | while read -r pkg; do
477 local right=osh-as-sh/log/$pkg.log.txt
478
479 local cause
480 cause=$(awk -f $cause_awk $right)
481
482 local suite=''
483 local suite_HREF=''
484 local suite_path="osh-as-sh/test-suite/$pkg/test-suite.log.txt"
485 if test -f "$suite_path"; then
486 suite='suite'
487 suite_HREF=$suite_path # shard added in regtest/aports/merge.sql
488 fi
489
490 echo "${pkg}${TAB}${cause}${TAB}${suite}${TAB}${suite_HREF}"
491 done
492 } > causes.tsv
493
494 # Import causes.tsv and add columns
495 sqlite-tabs-headers \
496 -cmd '.import causes.tsv causes' \
497 $db < $cause_sql
498
499 # The DB is diff_baseline.db, with table diff_baseline
500 db-to-tsv $db diff_baseline
501
502 popd > /dev/null
503}
504
505db-to-tsv() {
506 local db=$1
507 local table_name=$2
508 local order_by=${3:-}
509
510 echo "
511 select * from ${table_name} ${order_by};
512 " | sqlite-tabs-headers $db >$table_name.tsv
513
514 echo "
515 create table ${table_name}_schema as
516 select
517 name as column_name,
518 case
519 when UPPER(type) like '%INT%' then 'integer'
520 when UPPER(type) = 'REAL' then 'float'
521 when UPPER(type) = 'TEXT' then 'string'
522 else LOWER(type)
523 end as type
524 from PRAGMA_TABLE_INFO('${table_name}');
525
526 select * from ${table_name}_schema;
527 " | sqlite-tabs-headers $db >$table_name.schema.tsv
528}
529
530merge-diffs-sql() {
531 local -a SHARDS=( "$@" )
532
533 local is_first_shard=T
534
535 # Now insert data from all the shards
536 for ((i=0; i<${#SHARDS[@]}; i++)); do
537 local shard_dir="${SHARDS[i]}"
538 shard_name=$(basename $shard_dir)
539
540 # Handle incomplete shard
541 if ! test -d $shard_dir/baseline || ! test -d $shard_dir/osh-as-sh; then
542 continue
543 fi
544
545 echo "ATTACH DATABASE '$shard_dir/diff_baseline.db' AS temp_shard;"
546
547 if test -n "$is_first_shard"; then
548 # Create table from first shard
549 echo "
550 CREATE TABLE diff_merged AS
551 SELECT *, CAST('' as TEXT) as shard FROM temp_shard.diff_baseline where 1=0;
552
553 CREATE TABLE metrics AS
554 SELECT *, CAST('' as TEXT) as shard FROM temp_shard.metrics where 1=0;
555 "
556 is_first_shard='' # don't create table next time
557 fi
558
559 # Now insert data
560 echo "
561 INSERT INTO diff_merged
562 SELECT *, '$shard_name' as shard FROM temp_shard.diff_baseline;
563
564 INSERT INTO metrics
565 SELECT *, '$shard_name' as shard FROM temp_shard.metrics;
566
567 DETACH DATABASE temp_shard;
568 "
569 done
570
571 # Does not involve metaprogramming
572 cat regtest/aports/merge.sql
573}
574
575merge-diffs() {
576 local epoch_dir=${1:-_tmp/aports-report/2025-10-15-main}
577 local do_disagree=${2:-}
578
579 local db=$PWD/$epoch_dir/diff_merged.db
580 rm -f $db
581
582 local -a shards
583 if test -n "$do_disagree"; then
584 # Hack: distinguish disagree-2025 from disagree-packages.txt
585 shards=( $epoch_dir/disagree-2* ) # Usually 1 shard
586 else
587 shards=( $epoch_dir/shard* )
588 fi
589
590 echo SHARDS "${shards[@]}"
591
592 merge-diffs-sql "${shards[@]}" | sqlite3 $db
593 #echo $db
594
595 # copied from above
596 pushd $epoch_dir > /dev/null
597
598 db-to-tsv $db diff_merged 'order by pkg'
599 db-to-tsv $db metrics
600
601 db-to-tsv $db notable_disagree 'order by pkg'
602 db-to-tsv $db baseline_only 'order by pkg'
603 db-to-tsv $db other_fail 'order by pkg'
604 db-to-tsv $db timeout 'order by pkg'
605
606 # For re-running failures
607 sqlite3 diff_merged.db >disagree-packages.txt <<EOF
608.headers off
609select pkg from diff_merged where disagree = 1 and timeout = 0;
610EOF
611 #wc -l disagree-packages.txt
612
613 popd > /dev/null
614
615 local title1='OSH Disagreements - regtest/aports'
616 local out=$epoch_dir/diff_merged.html
617 merge-diff-html $epoch_dir '../../../web' "$title1" > $out
618 echo "Wrote $out"
619
620 local name2=metrics
621 local title2='Metrics - regtest/aports'
622 local out=$epoch_dir/$name2.html
623 table-page-html $epoch_dir $name2 '../../../web' "$title2" > $out
624 echo "Wrote $out"
625
626 # After merging, regenerate other stuff too
627
628 html-tree "$epoch_dir"
629
630 update-published # also done in deploy-published
631}
632
633write-shard-reports() {
634 local base_dir=$1 # e.g. _tmp/aports-report/2025-08-02/shard3
635
636 index-html > $base_dir/index.html
637
638 for config in baseline osh-as-sh; do
639 # Incomplete shard
640 if ! test -d "$base_dir/$config"; then
641 return
642 fi
643 write-tables-for-config "$base_dir" "$config"
644 done
645
646 local name=diff_baseline
647 local title="$base_dir differences"
648 make-diff-db $base_dir
649 table-page-html $base_dir $name '' "$title" > $base_dir/$name.html
650 echo "Wrote $base_dir/$name.html"
651}
652
653write-all-reports() {
654 local epoch_dir=${1:-_tmp/aports-report/2025-08-03}
655
656 for shard_dir in $epoch_dir/shard*; do
657 write-shard-reports "$shard_dir"
658 done
659
660 merge-diffs "$epoch_dir"
661}
662
663write-disagree-reports() {
664 local epoch_dir=${1:-_tmp/aports-build/2025-09-27}
665
666 # Hack: distinguish disagree-2025 from disagree-packages.txt
667 for shard_dir in $epoch_dir/disagree-2*; do
668 write-shard-reports "$shard_dir"
669 done
670
671 merge-diffs "$epoch_dir" T
672}
673
674html-tree() {
675 local epoch_dir=${1:-_tmp/aports-report/2025-08-07-fix}
676
677 local epoch
678 epoch=$(basename $epoch_dir)
679
680 pushd $epoch_dir
681 # -L 3 goes 3 levels deeps, omitting logs
682 tree \
683 -H './' \
684 -T "regtest/aports - $epoch" \
685 -L 3 \
686 --charset=ascii \
687 > tree.html
688 popd
689
690 echo "Wrote $epoch_dir/tree.html"
691}
692
693update-published() {
694 local out=$REPORT_DIR/published.html
695 published-html > $out
696 echo "Wrote $out"
697}
698
699remove-apk() {
700 local base_dir=${1:-$REPORT_DIR/2025-09-07}
701 # temporary
702
703 find $base_dir -name '*.apk' -o -name 'APKINDEX*' | xargs -d $'\n' --verbose -- rm -v
704}
705
706make-wwz() {
707 local base_dir=${1:-$REPORT_DIR/2025-08-03}
708
709 # must not end with slash
710 base_dir=${base_dir%'/'}
711
712 local wwz=$base_dir.wwz
713 rm -f -v $wwz
714
715 zip -r $wwz $base_dir web/
716
717 echo "Wrote $wwz"
718}
719
720readonly WEB_HOST=op.oils.pub
721
722deploy-wwz-op() {
723 local wwz=${1:-$REPORT_DIR/2025-08-03.wwz}
724
725 local dest_dir=$WEB_HOST/aports-build
726
727 update-published # slightly redundant
728
729 ssh $WEB_HOST mkdir -p $dest_dir
730
731 scp $wwz $REPORT_DIR/published.html \
732 $WEB_HOST:$dest_dir/
733
734 echo "Visit https://$dest_dir/published.html"
735 echo " https://$dest_dir/$(basename $wwz)/"
736}
737
738deploy-published() {
739 local dest_dir=$WEB_HOST/aports-build
740
741 update-published # slightly redundant
742
743 scp $REPORT_DIR/published.html \
744 $WEB_HOST:$dest_dir/
745
746 echo "Visit https://$dest_dir/published.html"
747}
748
749#
750# For editing
751#
752
753readonly EDIT_DIR=_tmp/aports-edit
754
755readonly EDITING_APORTS_EPOCH='2025-10-22-comm.wwz'
756
757sync-old-wwz() {
758 local wwz=${1:-$EDITING_APORTS_EPOCH}
759
760 mkdir -p $EDIT_DIR
761
762 wget --directory $EDIT_DIR \
763 "https://$WEB_HOST/aports-build/$wwz"
764
765 ls -l $EDIT_DIR
766 #echo "Wrote $wwz"
767}
768
769extract-old-wwz() {
770 local new_epoch=$1
771 local wwz=${2:-$EDITING_APORTS_EPOCH}
772
773 # Extract the whole thing into a temp dir
774 local tmp_dir=$EDIT_DIR/$new_epoch
775 rm -r -f $tmp_dir
776 mkdir -p $tmp_dir
777
778 pushd $tmp_dir
779 unzip ../$wwz
780 popd
781
782 # Now re-create the old structure under _tmp/aports-report/2025-09-06-edit
783
784 local dest_dir=$REPORT_DIR/$new_epoch
785 mkdir -p $dest_dir
786
787 local old_epoch
788 old_epoch=$(basename $wwz .wwz)
789 mv -v --no-target-directory $tmp_dir/_tmp/aports-report/$old_epoch $dest_dir
790}
791
792sync-extract-both() {
793 local main=2025-10-22.wwz
794 local comm=2025-10-22-comm.wwz
795
796 sync-old-wwz $main
797 sync-old-wwz $comm
798
799 extract-old-wwz 2025-11-01-main-cause $main
800 extract-old-wwz 2025-11-01-comm-cause $comm
801}
802
803#
804# Dev tools
805#
806
807out-of-vm() {
808 local dest=~/vm-shared/$EPOCH
809 mkdir -p $dest
810 cp $REPORT_DIR/$EPOCH.wwz $dest
811 pushd ~/vm-shared/$EPOCH
812 unzip $EPOCH.wwz
813 popd
814}
815
816task-five "$@"