boklm pushed to branch main at The Tor Project / Applications / tor-browser-bundle-testsuite
Commits:
-
d7f73057
by Nicolas Vigier at 2026-07-30T17:00:17+02:00
9 changed files:
- .gitignore
- + TBBTestSuite/TestSuite/TorBrowserBuildGitlabPipelines.pm
- TBBTestSuite/TestSuites.pm
- config/tb-build-06.torproject.org
- + config/tb-build-06.torproject.org-gitlab-pipelines
- + tmpl/details_gitlab_pipeline.html
- + tmpl/report_tor-browser_pipelines.txt
- + tmpl/reports_index_tor-browser_pipelines.html
- tools/tb-build-06-start-nightly-build
Changes:
| ... | ... | @@ -7,3 +7,4 @@ reports |
| 7 | 7 | tmp
|
| 8 | 8 | bundle
|
| 9 | 9 | tools/.gitlab_trigger_token
|
| 10 | +gitlab-tokens |
| 1 | +package TBBTestSuite::TestSuite::TorBrowserBuildGitlabPipelines;
|
|
| 2 | + |
|
| 3 | +use strict;
|
|
| 4 | +use parent 'TBBTestSuite::TestSuite';
|
|
| 5 | + |
|
| 6 | +use FindBin;
|
|
| 7 | +use TBBTestSuite::Common qw(run_to_file exit_error);
|
|
| 8 | +use TBBTestSuite::GitRepo;
|
|
| 9 | +use TBBTestSuite::Options qw($options);
|
|
| 10 | +use File::Copy;
|
|
| 11 | +use File::Slurp;
|
|
| 12 | +use IO::CaptureOutput qw(capture_exec);
|
|
| 13 | +use Path::Tiny;
|
|
| 14 | +use LWP::UserAgent;
|
|
| 15 | +use JSON;
|
|
| 16 | +use Data::Dump qw/dd/;
|
|
| 17 | + |
|
| 18 | +sub description {
|
|
| 19 | + 'Tor Browser Build Gitlab Pipelines';
|
|
| 20 | +}
|
|
| 21 | + |
|
| 22 | +sub type {
|
|
| 23 | + 'tor-browser_pipelines';
|
|
| 24 | +};
|
|
| 25 | + |
|
| 26 | +sub test_types {
|
|
| 27 | + return {
|
|
| 28 | + gitlab_pipeline => \&gitlab_pipeline,
|
|
| 29 | + }
|
|
| 30 | +}
|
|
| 31 | + |
|
| 32 | +sub gitlab_access_token {
|
|
| 33 | + my $token_dir = "$FindBin::Bin/gitlab-tokens";
|
|
| 34 | + my $token_file = "$token_dir/access-token";
|
|
| 35 | + exit_error "File $token_file is missing" unless -f $token_file;
|
|
| 36 | + # Change permission on gitlab-tokens directory to make sure token files
|
|
| 37 | + # cannot be accessed by other users
|
|
| 38 | + chmod 0700, $token_dir;
|
|
| 39 | + my $token = read_file($token_file);
|
|
| 40 | + chomp $token;
|
|
| 41 | + return $token;
|
|
| 42 | +}
|
|
| 43 | + |
|
| 44 | +sub get_ua {
|
|
| 45 | + my $token = gitlab_access_token;
|
|
| 46 | + my $ua = LWP::UserAgent->new;
|
|
| 47 | + $ua->default_header('PRIVATE-TOKEN' => $token);
|
|
| 48 | + return $ua;
|
|
| 49 | +}
|
|
| 50 | + |
|
| 51 | +sub get_pipeline_status {
|
|
| 52 | + my ($pipeline_id) = @_;
|
|
| 53 | + my $ua = get_ua;
|
|
| 54 | + my $url = "https://gitlab.torproject.org/api/v4/projects/409/pipelines/$pipeline_id";
|
|
| 55 | + my $count = 100;
|
|
| 56 | + while ($count) {
|
|
| 57 | + my $response = $ua->get($url);
|
|
| 58 | + if ($response->is_success) {
|
|
| 59 | + my $result = eval { decode_json $response->decoded_content };
|
|
| 60 | + my %finished_status = map { $_ => 1 }
|
|
| 61 | + qw/success failed canceling canceled skipped/;
|
|
| 62 | + if (ref $result eq 'HASH' && $result->{status}
|
|
| 63 | + && $finished_status{$result->{status}}) {
|
|
| 64 | + return $result->{status};
|
|
| 65 | + }
|
|
| 66 | + }
|
|
| 67 | + $count--;
|
|
| 68 | + sleep 60;
|
|
| 69 | + }
|
|
| 70 | + return 'timeout';
|
|
| 71 | +}
|
|
| 72 | + |
|
| 73 | +sub get_failed_jobs {
|
|
| 74 | + my ($pipeline_id) = @_;
|
|
| 75 | + my @res;
|
|
| 76 | + my $ua = get_ua;
|
|
| 77 | + my $url = "https://gitlab.torproject.org/api/v4/projects/409/pipelines/$pipeline_id/jobs?scope[]=failed";
|
|
| 78 | + my $response = $ua->get($url);
|
|
| 79 | + return \@res unless $response->is_success;
|
|
| 80 | + my $result = eval { decode_json $response->decoded_content };
|
|
| 81 | + return \@res unless ref $result eq 'ARRAY';
|
|
| 82 | + foreach my $job (@$result) {
|
|
| 83 | + push @res, {
|
|
| 84 | + id => $job->{id},
|
|
| 85 | + url => "https://gitlab.torproject.org/tpo/applications/tor-browser-bundle-testsuite/-/jobs/$job->{id}",
|
|
| 86 | + name => $job->{name},
|
|
| 87 | + failure_reason => $job->{failure_reason},
|
|
| 88 | + };
|
|
| 89 | + }
|
|
| 90 | + return \@res;
|
|
| 91 | +}
|
|
| 92 | + |
|
| 93 | +sub gitlab_pipeline {
|
|
| 94 | + my ($testsuite, $test) = @_;
|
|
| 95 | + $test->{results}{success} = 0;
|
|
| 96 | + my $pipeline_id;
|
|
| 97 | + $pipeline_id = $1
|
|
| 98 | + if $test->{gitlab_pipeline_url} =~ m{https://gitlab.torproject.org/tpo/applications/tor-browser-bundle-testsuite/-/pipelines/(\d+)};
|
|
| 99 | + return unless $pipeline_id;
|
|
| 100 | + my $status = get_pipeline_status($pipeline_id);
|
|
| 101 | + $test->{pipeline_status} = $status;
|
|
| 102 | + $test->{results}{success} = 1 if $status eq 'success';
|
|
| 103 | + $test->{failed_jobs} = get_failed_jobs($pipeline_id)
|
|
| 104 | + if $status eq 'failed';
|
|
| 105 | +}
|
|
| 106 | + |
|
| 107 | +sub set_tests {
|
|
| 108 | + my ($testsuite) = @_;
|
|
| 109 | + exit_error "tbb_buildreport_dir option is missing" unless $testsuite->{tbb_buildreport_dir};
|
|
| 110 | + $testsuite->{tests} = [];
|
|
| 111 | + my $tbb_buildreport = $testsuite->{tbb_buildreport_dir};
|
|
| 112 | + return unless -d $tbb_buildreport;
|
|
| 113 | + foreach my $pipeline (path($tbb_buildreport)->children(qr/\.trigger-test-pipeline\.stdout\.txt\z/)) {
|
|
| 114 | + my $url = $pipeline->slurp_utf8;
|
|
| 115 | + my $name = $pipeline->basename;
|
|
| 116 | + if ($name =~ m/^(.+)\.trigger-test-pipeline\.stdout\.txt\z/) {
|
|
| 117 | + my $test_name = "pipeline-$1";
|
|
| 118 | + push @{$testsuite->{tests}}, {
|
|
| 119 | + name => $test_name,
|
|
| 120 | + descr => $test_name,
|
|
| 121 | + type => 'gitlab_pipeline',
|
|
| 122 | + gitlab_pipeline_url => $url,
|
|
| 123 | + };
|
|
| 124 | + }
|
|
| 125 | + }
|
|
| 126 | +}
|
|
| 127 | + |
|
| 128 | +sub new {
|
|
| 129 | + my ($ts, $infos) = @_;
|
|
| 130 | + my $testsuite = {
|
|
| 131 | + %$infos,
|
|
| 132 | + type => $ts->type(),
|
|
| 133 | + filename => $ts->type(),
|
|
| 134 | + };
|
|
| 135 | + bless $testsuite, $ts;
|
|
| 136 | + $testsuite->set_tests();
|
|
| 137 | + return $testsuite;
|
|
| 138 | +}
|
|
| 139 | + |
|
| 140 | +1; |
| ... | ... | @@ -7,11 +7,12 @@ use TBBTestSuite::TestSuite::BrowserBundleTests; |
| 7 | 7 | use TBBTestSuite::TestSuite::BrowserUnitTests;
|
| 8 | 8 | use TBBTestSuite::TestSuite::RBMBuild;
|
| 9 | 9 | use TBBTestSuite::TestSuite::TorBrowserBuild;
|
| 10 | +use TBBTestSuite::TestSuite::TorBrowserBuildGitlabPipelines;
|
|
| 10 | 11 | use TBBTestSuite::TestSuite::BrowserBundleHardening;
|
| 11 | 12 | |
| 12 | 13 | my @testsuite_list = qw(TestTestSuite BrowserBundleTests
|
| 13 | 14 | BrowserUnitTests RBMBuild TorBrowserBuild
|
| 14 | - BrowserBundleHardening);
|
|
| 15 | + TorBrowserBuildGitlabPipelines BrowserBundleHardening);
|
|
| 15 | 16 | my %testsuite_types;
|
| 16 | 17 | sub testsuite_types {
|
| 17 | 18 | return %testsuite_types if %testsuite_types;
|
| ... | ... | @@ -7,6 +7,7 @@ use File::Slurp; |
| 7 | 7 | use TBBTestSuite::TestSuite::TorBrowserBuild;
|
| 8 | 8 | |
| 9 | 9 | my $date = DateTime->now->ymd;
|
| 10 | +$date = $ENV{NIGHTLY_BUILD_DATE} if $ENV{NIGHTLY_BUILD_DATE};
|
|
| 10 | 11 | my $tbb_version = 'tbb-nightly.' . DateTime->now->ymd('.');
|
| 11 | 12 | my $name = "tor-browser-$date";
|
| 12 | 13 |
| 1 | +# vim: filetype=perl expandtab
|
|
| 2 | +use strict;
|
|
| 3 | +use FindBin;
|
|
| 4 | +use DateTime;
|
|
| 5 | +use TBBTestSuite::TestSuite::TorBrowserBuildGitlabPipelines;
|
|
| 6 | + |
|
| 7 | +my $date = DateTime->now->ymd;
|
|
| 8 | +$date = $ENV{NIGHTLY_BUILD_DATE} if $ENV{NIGHTLY_BUILD_DATE};
|
|
| 9 | +my $name = "tor-browser-pipelines-$date";
|
|
| 10 | + |
|
| 11 | +my $builds_dir_root = '/home/tb-builder/nightly-builds';
|
|
| 12 | +my $reports_dir = "$builds_dir_root/reports";
|
|
| 13 | + |
|
| 14 | +if (-d "$reports_dir/r/$name") {
|
|
| 15 | + print "Doing nothing: $name already done\n";
|
|
| 16 | + return ( args => [] );
|
|
| 17 | +}
|
|
| 18 | + |
|
| 19 | +my $testsuite = TBBTestSuite::TestSuite::TorBrowserBuildGitlabPipelines->new({
|
|
| 20 | + tbb_buildreport_dir => "$reports_dir/r/tor-browser-$date/results-tor-browser_build",
|
|
| 21 | + });
|
|
| 22 | + |
|
| 23 | +my %res = (
|
|
| 24 | + name => $name,
|
|
| 25 | + args => [ $testsuite ],
|
|
| 26 | + tags => [ 'nightly' ],
|
|
| 27 | + 'default-retry' => 1,
|
|
| 28 | + 'reports-dir' => $reports_dir,
|
|
| 29 | + 'reports-url' => 'https://nightlies.tbb.torproject.org/nightly-builds/reports/',
|
|
| 30 | + 'email-subject' => '[pipelines result: [% tbbfile = "tor-browser_pipelines"; tbbfiles.$tbbfile.tests.size == 0 ? "skipped" : success ? "ok" : "failed" %]] [% options.name %]',
|
|
| 31 | + 'email-report' => 1,
|
|
| 32 | + 'email-to' => [
|
|
| 33 | + 'bea@xxxxxxxxxxxxxx',
|
|
| 34 | + 'boklm@xxxxxxxxxxxxxx',
|
|
| 35 | + 'clairehurst@xxxxxxxxxxxxxx',
|
|
| 36 | + 'dan@xxxxxxxxxxxxxx',
|
|
| 37 | + 'henry@xxxxxxxxxxxxxx',
|
|
| 38 | + 'jwilde@xxxxxxxxxxxxxx',
|
|
| 39 | + 'ma1@xxxxxxxxxxxxxx',
|
|
| 40 | + 'morgan@xxxxxxxxxxxxxx',
|
|
| 41 | + 'pierov@xxxxxxxxxxxxxx',
|
|
| 42 | + ],
|
|
| 43 | + 'email-from' => 'Tor Browser Nightly Builds <tb-builder@xxxxxxxxxxxxxxxxxxxxxxxxxx>',
|
|
| 44 | +);
|
|
| 45 | +%res; |
| 1 | +<ul>
|
|
| 2 | +[% IF test.pipeline_status %]
|
|
| 3 | + <li>Status: [% test.pipeline_status %]
|
|
| 4 | +[% END %]
|
|
| 5 | + <li><a href="">"[% test.gitlab_pipeline_url %]">GitLab test pipeline</a></li>
|
|
| 6 | +[% IF test.failed_jobs %]
|
|
| 7 | + [% FOREACH job = test.failed_jobs %]
|
|
| 8 | + <li>Failed job: <a href="">"[% job.url %]">[% job.name %](#[% job.id %])</a> - [% job.failure_reason %]</li>
|
|
| 9 | + [% END %]
|
|
| 10 | +[% END %]
|
|
| 11 | +</ul> |
| 1 | +Results
|
|
| 2 | +[% IF tbbfiles.$tbbfile.tests.size == 0 -%]
|
|
| 3 | + |
|
| 4 | + No pipeline has been run in today's nightly builds.
|
|
| 5 | + |
|
| 6 | +[% END -%]
|
|
| 7 | +[% FOREACH test IN tbbfiles.$tbbfile.tests -%]
|
|
| 8 | +[% IF test.results -%]
|
|
| 9 | + [% test.name %]: [% test.results.success ? 'ok' : 'failed (' _ test.fail_type _ ')' %]
|
|
| 10 | + |
|
| 11 | + GitLab test pipeline: [% test.gitlab_pipeline_url ? test.gitlab_pipeline_url : 'failed run' %]
|
|
| 12 | +[% IF test.failed_jobs -%]
|
|
| 13 | + [%- FOREACH job = test.failed_jobs -%]
|
|
| 14 | + Failed job ([% job.failure_reason %]): [% job.url %]
|
|
| 15 | + [%- END -%]
|
|
| 16 | + |
|
| 17 | +[% END -%]
|
|
| 18 | + |
|
| 19 | +[% END -%]
|
|
| 20 | +[% END %] |
| 1 | +[% USE date -%]
|
|
| 2 | +<html>
|
|
| 3 | + <head>
|
|
| 4 | + <title>Tests reports</title>
|
|
| 5 | + <style type="text/css">
|
|
| 6 | + .test_ok {
|
|
| 7 | + color: #006600;
|
|
| 8 | + font-weight: bold;
|
|
| 9 | + }
|
|
| 10 | + .test_ok A {
|
|
| 11 | + color: #006600;
|
|
| 12 | + font-weight: bold;
|
|
| 13 | + }
|
|
| 14 | + .test_notok {
|
|
| 15 | + color: #FF0000;
|
|
| 16 | + font-weight: bold;
|
|
| 17 | + }
|
|
| 18 | + .test_notok A {
|
|
| 19 | + color: #FF0000;
|
|
| 20 | + }
|
|
| 21 | + .reportdate {
|
|
| 22 | + font-size: small;
|
|
| 23 | + }
|
|
| 24 | + </style>
|
|
| 25 | + </head>
|
|
| 26 | + <body>
|
|
| 27 | + <h1>[% title %]</h1>
|
|
| 28 | + <table>
|
|
| 29 | + <tr>
|
|
| 30 | + <th>Name</th>
|
|
| 31 | + <th>Date</th>
|
|
| 32 | + <th>Version</th>
|
|
| 33 | + <th>Result</th>
|
|
| 34 | + </tr>
|
|
| 35 | + [% FOREACH report IN reports_list %]
|
|
| 36 | + <tr>
|
|
| 37 | + <td valign="top"><a href="">"r/[% report %]/[% testsuite_type %].html">[% report %]</a></td>
|
|
| 38 | + <td valign="top">[% date.format(reports.$report.time, '%Y-%m-%d %H:%M') %]</td>
|
|
| 39 | + <td valign="top">[% IF reports.$report.options.tags %]
|
|
| 40 | + <a href="">"index-[% testsuite_type %]-[% reports.$report.options.tags.0 %].html">[% reports.$report.options.tags.0 %]</a>
|
|
| 41 | + [% END %]
|
|
| 42 | + </td>
|
|
| 43 | + <td valign="top">
|
|
| 44 | + [% failed = 0 %]
|
|
| 45 | + [% SET tbbfile = reports.$report.tbbfiles.keys.0 -%]
|
|
| 46 | + [% FOREACH test IN reports.$report.tbbfiles.$tbbfile.tests %]
|
|
| 47 | + [% NEXT UNLESS test.results %]
|
|
| 48 | + [% IF test.results.success %]
|
|
| 49 | + <img src="">"static/ok-small.png" />
|
|
| 50 | + <span class="test_ok"><a href="">"r/[% report %]/[% testsuite_type %].html">[% test.name %]</a></span>
|
|
| 51 | + [% ELSE -%]
|
|
| 52 | + <img src="">"static/failed-small.png" />
|
|
| 53 | + <span class="test_notok"><a href="">"r/[% report %]/[% tbbfile %].html">[% test.name %]</a></span>
|
|
| 54 | + [% END -%]
|
|
| 55 | + [% END -%]
|
|
| 56 | + </td>
|
|
| 57 | + </tr>
|
|
| 58 | + [% END %]
|
|
| 59 | + </table>
|
|
| 60 | + </body>
|
|
| 61 | +</html> |
| ... | ... | @@ -22,6 +22,7 @@ function getlock { |
| 22 | 22 | getlock
|
| 23 | 23 | |
| 24 | 24 | today_version=$(date '+tbb-nightly.%Y.%m.%d')
|
| 25 | +export NIGHTLY_BUILD_DATE=$(date +"%Y-%m-%d")
|
|
| 25 | 26 | |
| 26 | 27 | cd /home/tb-builder/tor-browser-bundle-testsuite
|
| 27 | 28 | export RBM_NO_DEBUG=1
|
| ... | ... | @@ -73,6 +74,8 @@ builds_size=$(du -s ~/nightly-builds/tor-browser-builds | cut -f 1) |
| 73 | 74 | test "$builds_size" -gt 20000000 && \
|
| 74 | 75 | /home/tb-builder/tor-browser-bundle-testsuite/clones/tor-browser-build/tools/prune-old-builds --days 7 --weeks 0 --months 0 ~/nightly-builds/tor-browser-builds
|
| 75 | 76 | |
| 77 | +./tbb-testsuite --config=tb-build-06.torproject.org-gitlab-pipelines "$@"
|
|
| 78 | + |
|
| 76 | 79 | # sleep for 5m to give time to previous rsync to finish
|
| 77 | 80 | sleep 5m
|
| 78 | 81 | /home/tb-builder/tor-browser-bundle-testsuite/tools/rsync-to-tbb-nightlies-master |