brizental pushed to branch main at The Tor Project / Applications / tor-browser-bundle-testsuite Commits: ce7fa79b by Beatriz Rizental at 2026-09-16T14:32:16-03:00 Bug 40107: Execute xpcshell tests on CI - - - - - 03eca1fb by Beatriz Rizental at 2026-09-16T16:09:52-03:00 Bug 40107: Pass base-browser as a test tag for all browsers - - - - - 8 changed files: - .gitlab-ci.yml - .gitlab/_base.yml - .gitlab/_inputs.yml - .gitlab/scripts/before_script.py - .gitlab/test_marionette.yml - + .gitlab/test_xpcshell.yml - config/tb-build-06.torproject.org - tools/trigger-test-pipeline.py Changes: ===================================== .gitlab-ci.yml ===================================== @@ -3,6 +3,7 @@ spec: - local: '.gitlab/_inputs.yml' --- stages: + - test-xpcshell - test-marionette default: @@ -17,7 +18,7 @@ include: - local: '.gitlab/_base.yml' inputs: mozharness_url: $[[ inputs.mozharness_url ]] - tag: $[[ inputs.tag ]] + tags: $[[ inputs.tags ]] android_x86_64_installer_url: $[[ inputs.android_x86_64_installer_url ]] android_x86_64_package_name: $[[ inputs.android_x86_64_package_name ]] android_x86_64_artifacts_url: $[[ inputs.android_x86_64_artifacts_url ]] @@ -31,4 +32,5 @@ include: windows_x86_64_installer_url: $[[ inputs.windows_x86_64_installer_url ]] windows_x86_64_artifacts_url: $[[ inputs.windows_x86_64_artifacts_url ]] windows_x86_64_sha256sums_url: $[[ inputs.windows_x86_64_sha256sums_url ]] + - local: '.gitlab/test_xpcshell.yml' - local: '.gitlab/test_marionette.yml' ===================================== .gitlab/_base.yml ===================================== @@ -4,9 +4,10 @@ spec: --- variables: MOZHARNESS_URL: "$[[ inputs.mozharness_url ]]" - TAG: "$[[ inputs.tag ]]" + TAGS: "$[[ inputs.tags ]]" .common: + allow_failure: true before_script: - python3 .gitlab/scripts/before_script.py @@ -16,6 +17,10 @@ variables: .debian-x86_64: extends: .common + before_script: + - Xvfb :99 -screen 0 1280x1024x24 >/dev/null 2>&1 & + - !reference [.common, before_script] + tags: - debian-trixie-x86_64 @@ -25,9 +30,11 @@ variables: - when: never variables: + DISPLAY: ":99" MOZ_FETCHES_DIR: "/home/gitlab-runner/fetches" MINIDUMP_STACKWALK_URL: "https://github.com/rust-minidump/rust-minidump/releases/download/v0.26.1/min..." MINIDUMP_STACKWALK_SHA256: "f789997f086dab6e46c46ab4560fc28676124613770ddac3b89a6e2e0e4963d8" + NODEJS_PATH: "/home/gitlab-runner/.nvm/versions/node/v22.16.0/bin/node" INSTALLER_URL: "$[[ inputs.debian_x86_64_installer_url ]]" ARTIFACTS_URL: "$[[ inputs.debian_x86_64_artifacts_url ]]" SHA256SUMS_URL: "$[[ inputs.debian_x86_64_sha256sums_url ]]" @@ -35,6 +42,11 @@ variables: .macos-x86_64: extends: .common + # Overwrite just so we can change $PATH + before_script: + - export PATH="/usr/local/bin:$PATH" + - !reference [.common, before_script] + tags: - macos-sonoma-x86_64 @@ -47,6 +59,7 @@ variables: MOZ_FETCHES_DIR: "/Users/gitlab-runner/fetches" MINIDUMP_STACKWALK_URL: "https://github.com/rust-minidump/rust-minidump/releases/download/v0.26.1/min..." MINIDUMP_STACKWALK_SHA256: "7a3e274a09bc35ccc35e9d3dcd60e738ab14e54ea3306be94a4a8dedaf7a468d" + NODEJS_PATH: "/Users/gitlab-runner/.nvm/versions/node/v22.16.0/bin/node" INSTALLER_URL: "$[[ inputs.macos_x86_64_installer_url ]]" ARTIFACTS_URL: "$[[ inputs.macos_x86_64_artifacts_url ]]" SHA256SUMS_URL: "$[[ inputs.macos_x86_64_sha256sums_url ]]" @@ -66,6 +79,7 @@ variables: MOZ_FETCHES_DIR: 'C:\windoes\fetches' MINIDUMP_STACKWALK_URL: 'https://github.com/rust-minidump/rust-minidump/releases/download/v0.26.1/min...' MINIDUMP_STACKWALK_SHA256: "dc6da411047ef15b784bffe0f9bf7ecb9221186c4c8fd655e3d8a3fbba0a9c61" + NODEJS_PATH: 'C:\Program Files\nodejs\node.exe' INSTALLER_URL: "$[[ inputs.windows_x86_64_installer_url ]]" ARTIFACTS_URL: "$[[ inputs.windows_x86_64_artifacts_url ]]" SHA256SUMS_URL: "$[[ inputs.windows_x86_64_sha256sums_url ]]" ===================================== .gitlab/_inputs.yml ===================================== @@ -3,10 +3,10 @@ inputs: type: string default: "" description: "Location of the mozharness.zip archive" - tag: + tags: type: string default: "" - description: "Tag used to filter tests" + description: "Space-separated --tag flags (e.g. '--tag foo --tag bar'). Will run all tests if not provided" android_x86_64_installer_url: type: string ===================================== .gitlab/scripts/before_script.py ===================================== @@ -1,5 +1,6 @@ import hashlib import os +import platform import shutil import subprocess import time @@ -32,12 +33,17 @@ def download_file(url: str, dest: Path, sha256: str = "") -> None: def extract_tar(tar_path: Path, dest_dir: Path) -> None: - subprocess.run( + result = subprocess.run( # --strip-components=1: all the archives we fetch have contents nested inside a # top-level directory rather than at the root, so we strip it on extraction. - ["tar", "-xf", str(tar_path), "-C", str(dest_dir), "--strip-components=1"], - check=True, + # + # NOTE: The `v` flag is _required_ for tar to work on MacOS ¯\_(ツ)_/¯ + ["tar", f"-x{'v' if platform.system() == 'Darwin' else ''}f", str(tar_path), "-C", str(dest_dir), "--strip-components=1"], + stderr=subprocess.PIPE, + text=True, ) + if result.returncode != 0: + raise RuntimeError(f"tar failed (exit {result.returncode}):\n{result.stderr}") def check_sha256sums_url(sha256sums_url: str) -> None: @@ -159,6 +165,22 @@ def setup_android_sdk(moz_fetches_dir: str) -> None: print(f"Moved AVD -> {android_device_dir / 'avd'}") + +def download_hostutils(moz_fetches_dir: str) -> None: + # Stable mirror of https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/gecko.cache.lev... + HOSTUTILS_URL = "https://build-sources.tbb.torproject.org/hostutils.tar.zst" + HOSTUTILS_SHA256 = ( + "90ff9390181d7dc015c882f11e11800ef03be39f003c29b22bda01ad21c04a9e" + ) + + hostutils_dir = Path(moz_fetches_dir) / "hostutils" + hostutils_dir.mkdir(parents=True, exist_ok=True) + + tar_zst_path = Path("hostutils.tar.zst") + download_file(HOSTUTILS_URL, tar_zst_path, HOSTUTILS_SHA256) + extract_tar(tar_zst_path, hostutils_dir) + + def before_script( mozharness_url: str, minidump_stackwalk_url: str, @@ -175,6 +197,7 @@ def before_script( if setup_android: setup_android_sdk(moz_fetches_dir) + download_hostutils(moz_fetches_dir) if __name__ == "__main__": ===================================== .gitlab/test_marionette.yml ===================================== @@ -1,4 +1,5 @@ -.marionette-desktop: +debian-x86_64_marionette: + extends: .debian-x86_64 stage: test-marionette script: - > @@ -6,23 +7,32 @@ --config-file "$(pwd)/mozharness/configs/marionette/prod_config.py" --installer-url "$INSTALLER_URL" --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" - --tag "$TAG" --headless - -debian-x86_64_marionette: - extends: - - .debian-x86_64 - - .marionette-desktop + $TAGS macos-x86_64_marionette: - extends: - - .macos-x86_64 - - .marionette-desktop + extends: .macos-x86_64 + stage: test-marionette + script: + - > + python3 "$(pwd)/mozharness/scripts/marionette.py" + --config-file "$(pwd)/mozharness/configs/marionette/prod_config.py" + --installer-url "$INSTALLER_URL" + --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" + --headless + $TAGS windows-x86_64_marionette: - extends: - - .windows-x86_64 - - .marionette-desktop + extends: .windows-x86_64 + stage: test-marionette + script: + - > + python3 "$(pwd)/mozharness/scripts/marionette.py" + --config-file "$(pwd)/mozharness/configs/marionette/prod_config.py" + --installer-url "$INSTALLER_URL" + --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" + --headless + ($env:TAGS -split ' ') android-x86_64_marionette: extends: .android-x86_64 @@ -36,4 +46,4 @@ android-x86_64_marionette: --installer-url "$INSTALLER_URL" --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" --package-name "$PACKAGE_NAME" - --tag "$TAG" + $TAGS ===================================== .gitlab/test_xpcshell.yml ===================================== @@ -0,0 +1,50 @@ +debian-x86_64_xpcshell: + extends: .debian-x86_64 + stage: test-xpcshell + script: + - > + python3 "$(pwd)/mozharness/scripts/desktop_unittest.py" + --config-file "$(pwd)/mozharness/configs/unittests/linux_unittest.py" + --xpcshell-suite xpcshell + --installer-url "$INSTALLER_URL" + --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" + $TAGS + +macos-x86_64_xpcshell: + extends: .macos-x86_64 + stage: test-xpcshell + script: + - > + python3 "$(pwd)/mozharness/scripts/desktop_unittest.py" + --config-file "$(pwd)/mozharness/configs/unittests/mac_unittest.py" + --xpcshell-suite xpcshell + --installer-url "$INSTALLER_URL" + --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" + $TAGS + +windows-x86_64_xpcshell: + extends: .windows-x86_64 + stage: test-xpcshell + script: + - > + python3 "$(pwd)/mozharness/scripts/desktop_unittest.py" + --config-file "$(pwd)/mozharness/configs/unittests/win_unittest.py" + --xpcshell-suite xpcshell + --installer-url "$INSTALLER_URL" + --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" + --pip-index + ($env:TAGS -split ' ') + +android-x86_64_xpcshell: + extends: .android-x86_64 + stage: test-xpcshell + script: + - > + python3 "$(pwd)/mozharness/scripts/android_emulator_unittest.py" + --config-file "$(pwd)/mozharness/configs/android/android_common.py" + --config-file "$(pwd)/mozharness/configs/android/android14-x86_64.py" + --test-suite=xpcshell + --installer-url "$ARTIFACTS_URL/test_runner.apk" + --test-packages-url "$ARTIFACTS_URL/target.test_packages.json" + --package-name "$PACKAGE_NAME" + $TAGS ===================================== config/tb-build-06.torproject.org ===================================== @@ -37,13 +37,13 @@ my $test_post = sub { return unless $test->{results} && $test->{results}{success}; return unless $test->{publish_dir}; - my $tag = $test->{name} =~ /^torbrowser/ ? 'tor' : 'mullvad-browser'; + my $browser_tag = $test->{name} =~ /^torbrowser/ ? 'tor' : 'mullvad-browser'; my ($stdout, $stderr, $success) = capture_exec( 'python3', "$FindBin::Bin/tools/trigger-test-pipeline.py", '--step-name', $test->{name}, '--publish-url', $publish_url, '--publish-dir', $test->{publish_dir}, - '--tag', $tag, + '--tags', "$browser_tag,base-browser", ); write_file( "$tbbinfos->{'results-dir'}/$test->{name}.trigger-test-pipeline.stderr.txt", ===================================== tools/trigger-test-pipeline.py ===================================== @@ -35,6 +35,13 @@ def setup_logging() -> None: ) +def comma_separated_list(value): + items = [item.strip() for item in value.split(",") if item.strip()] + if not items: + raise argparse.ArgumentTypeError("must provide at least one tag") + return items + + def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Post-build trigger hook for triggering GitLab CI pipelines." @@ -59,9 +66,10 @@ def parse_args() -> argparse.Namespace: help="Subdirectory within the publish URL where build artifacts are located.", ) parser.add_argument( - "--tag", + "--tags", required=False, - help="Tag used to filter tests.", + type=comma_separated_list, + help="Comma separated list of tags used to filter tests. Will run all tests if not provided", ) parser.add_argument( "--dry-run", @@ -71,7 +79,7 @@ def parse_args() -> argparse.Namespace: return parser.parse_args() -def build_inputs(step_name: str, publish_url: str, publish_dir: str, tag: str) -> dict[str, str] | None: +def build_inputs(step_name: str, publish_url: str, publish_dir: str, tags: list[str] | None) -> 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] @@ -116,8 +124,8 @@ def build_inputs(step_name: str, publish_url: str, publish_dir: str, tag: str) - if platform == "android": inputs[f"{input_prefix}_package_name"] = f"org.torproject.{browser}_{channel}" - if tag: - inputs["tag"] = tag + if tags: + inputs["tags"] = " ".join(f"--tag {tag}" for tag in tags) return inputs @@ -157,7 +165,7 @@ def main() -> int: with open(token_file) as f: trigger_token = f.read().strip() - inputs = build_inputs(args.step_name, args.publish_url, args.publish_dir, args.tag) + inputs = build_inputs(args.step_name, args.publish_url, args.publish_dir, args.tags) if inputs is None: logger.info(f"No CI inputs for step {args.step_name!r}, skipping.") return 0 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)