brizental pushed to branch main at The Tor Project / Applications / tor-browser-bundle-testsuite Commits: 40d378be by Beatriz Rizental at 2026-04-29T13:47:55-03:00 Bug 40091: Implement script to trigger pipeline after nighly builds - - - - - 4 changed files: - .gitignore - config/tb-build-06.torproject.org - − tools/post-build-trigger.py - + tools/trigger-test-pipeline.py Changes: ===================================== .gitignore ===================================== @@ -6,3 +6,4 @@ virtualenv-marionette-* reports tmp bundle +tools/.gitlab_trigger_token ===================================== config/tb-build-06.torproject.org ===================================== @@ -37,9 +37,10 @@ my $test_post = sub { return unless $test->{publish_dir}; my ($stdout, $stderr, $success) = capture_exec( - 'python3', "$FindBin::Bin/tools/post-build-trigger.py", + 'python3', "$FindBin::Bin/tools/trigger-test-pipeline.py", '--step-name', $test->{name}, '--publish-url', $publish_url, + '--publish-dir', $test->{publish_dir}, ); print STDERR $stderr if $stderr; if (!$success) { ===================================== tools/post-build-trigger.py deleted ===================================== @@ -1,58 +0,0 @@ -#!/usr/bin/env python3 - -from __future__ import annotations - -import argparse -import logging -import sys - - -logger = logging.getLogger(__name__) - - -def setup_logging() -> None: - logging.basicConfig( - level=logging.INFO, - format="%(levelname)s: %(message)s", - # IMPORTANT! - # - # Perl captures this script's stdout and, if it is non-empty, stores it - # as `gitlab_pipeline_url` for the current build step. We need to keep logs - # on stderr and only print to stdout when its the resulting pipeline URL. - stream=sys.stderr, - ) - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser( - description="Post-build trigger hook for triggering GitLab CI pipelines." - ) - parser.add_argument( - "--step-name", - required=True, - help=""" - Name of the build step that just finished. - List of possible values can be found in - TBBTestSuite/TestSuite/TorBrowserBuild.pm (set_tests) - """, - ) - parser.add_argument( - "--publish-url", - required=True, - help="URL where build artifacts are published for the build artifacts.", - ) - return parser.parse_args() - - -def main() -> int: - setup_logging() - args = parse_args() - logger.info( - f"post-build-trigger.py not implemented yet " - f"(step={args.step_name}, publish_url={args.publish_url})" - ) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) ===================================== tools/trigger-test-pipeline.py ===================================== @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +import argparse +import json +import logging +import os +import sys +import urllib.request + +logger = logging.getLogger(__name__) + +GITLAB_URL = "https://gitlab.torproject.org" +# The project ID of the tor-browser-bundle-testsuite repository +GITLAB_PROJECT_ID = "409" +# We are running the pipeline on the main branch. +GITLAB_REF = "main" + +SUPPORTED_ARCHITECTURES_PER_PLATFORM = { + "linux": ["x86_64"], + "windows": ["x86_64"], + "macos": ["x86_64"], + "android": ["x86_64"], +} + + +def setup_logging() -> None: + logging.basicConfig( + level=logging.INFO, + format="%(levelname)s: %(message)s", + # IMPORTANT! + # + # Perl captures this script's stdout and, if it is non-empty, stores it + # as `gitlab_pipeline_url` for the current build step. We need to keep logs + # on stderr and only print to stdout when its the resulting pipeline URL. + stream=sys.stderr, + ) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Post-build trigger hook for triggering GitLab CI pipelines." + ) + parser.add_argument( + "--step-name", + required=True, + help=""" + Name of the build step that just finished. + List of possible values can be found in + TBBTestSuite/TestSuite/TorBrowserBuild.pm (set_tests) + """, + ) + parser.add_argument( + "--publish-url", + required=True, + help="URL where build artifacts are published for the build artifacts.", + ) + parser.add_argument( + "--publish-dir", + required=True, + help="Subdirectory within the publish URL where build artifacts are located.", + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Print the equivalent curl command instead of triggering the pipeline.", + ) + return parser.parse_args() + + +def build_inputs(step_name: str, publish_url: str, publish_dir: str) -> dict[str, str] | None: + # Add the architecture as padding, to address the macos case which doesn't + # have architecture in the step name since it is a universal build. + browser, channel, platform, architecture = (step_name.split("-") + ["x86_64"])[:4] + if channel != "nightly": + logger.info("This script only knows how to handle nightly builds. Skipping.") + return None + if ( + platform not in SUPPORTED_ARCHITECTURES_PER_PLATFORM + or architecture not in SUPPORTED_ARCHITECTURES_PER_PLATFORM[platform] + ): + logger.info( + f"Tests for {platform}-{architecture} are not supported yet. Skipping." + ) + return None + + hyphenated_browser = "tor-browser" if browser == "torbrowser" else "mullvad-browser" + date = publish_url.rstrip("/").split("/")[-1].split(".", 1)[1] + match platform: + case "linux": + installer = f"{hyphenated_browser}-{platform}-{architecture}-tbb-{channel}.{date}.tar.xz" + case "windows": + installer = f"{hyphenated_browser}-{platform}-{architecture}-portable-tbb-{channel}.{date}.exe" + case "macos": + installer = f"{hyphenated_browser}-{platform}-{architecture}-tbb-{channel}.{date}.dmg" + case "android": + installer = f"{hyphenated_browser}-qa-{platform}-{architecture}-tbb-{channel}.{date}.apk" + case _: + raise ValueError(f"Unsupported platform: {platform!r}. How did we get here?") + + artifacts_url = f"{publish_url}/{publish_dir}/artifacts/{platform}-{architecture}" + input_prefix = f"{'debian' if platform == 'linux' else platform}_{architecture}" + inputs = { + "mozharness_url": f"{artifacts_url}/mozharness.zip", + f"{input_prefix}_installer_url": f"{publish_url}/{publish_dir}/{installer}", + f"{input_prefix}_artifacts_url": artifacts_url, + } + + if platform == "android": + inputs[f"{input_prefix}_package_name"] = f"org.torproject.{browser}_{channel}" + + return inputs + + +def dry_run(inputs: dict[str, str], trigger_token: str) -> None: + url = f"{GITLAB_URL}/api/v4/projects/{GITLAB_PROJECT_ID}/trigger/pipeline?token={trigger_token}&ref={GITLAB_REF}" + payload = json.dumps({"inputs": inputs}, indent=2) + print( + f"curl --request POST --header 'Content-Type: application/json' --data '{payload}' '{url}'" + ) + + +def trigger_pipeline(trigger_token: str, inputs: dict[str, str]) -> str: + url = f"{GITLAB_URL}/api/v4/projects/{GITLAB_PROJECT_ID}/trigger/pipeline" + payload = json.dumps( + {"token": trigger_token, "ref": GITLAB_REF, "inputs": inputs} + ).encode() + req = urllib.request.Request( + url, + data=payload, + headers={"Content-Type": "application/json"}, + method="POST", + ) + with urllib.request.urlopen(req) as resp: + data = json.loads(resp.read()) + + return data["web_url"] + + +def main() -> int: + setup_logging() + args = parse_args() + + token_file = os.path.join( + os.path.dirname(os.path.abspath(__file__)), ".gitlab_trigger_token" + ) + with open(token_file) as f: + trigger_token = f.read().strip() + + inputs = build_inputs(args.step_name, args.publish_url, args.publish_dir) + if inputs is None: + logger.info(f"No CI inputs for step {args.step_name!r}, skipping.") + return 0 + + if args.dry_run: + dry_run(inputs, trigger_token) + return 0 + + logger.info(f"Triggering pipeline for step={args.step_name!r}") + pipeline_url = trigger_pipeline(trigger_token, inputs) + logger.info(f"Pipeline triggered: {pipeline_url}") + print(pipeline_url) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-bundle-testsuite/... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser-bundle-testsuite/... You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
participants (1)
-
brizental (@brizental)