def test_github_changed(mocker): """test github lists changed files in commit range""" repo = GitRepo(FIXTURES / "git02", "main", "FETCH_HEAD") try: evt = GithubEvent() evt.repo = repo evt.commit_range = "HEAD^..HEAD" changed_paths = set(evt.list_changed_paths()) assert changed_paths == {repo.path / "a.txt"} finally: repo.cleanup()
def test_create_03(mocker): """test push task creation""" taskcluster = mocker.patch("orion_decision.scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.commit = "commit" evt.branch = "push" evt.event_type = "push" evt.clone_url = "https://example.com" evt.pull_request = None sched = Scheduler(evt, now, "group", "secret", "push") sched.services["test1"].dirty = True sched.create_tasks() assert queue.createTask.call_count == 2 build_task_id, build_task = queue.createTask.call_args_list[0].args assert build_task == yaml_load( BUILD_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), dockerfile="test1/Dockerfile", expires=stringDate(now + ARTIFACTS_EXPIRE), load_deps="0", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, route="index.project.fuzzing.orion.test1.push", scheduler=SCHEDULER_ID, service_name="test1", source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) _, push_task = queue.createTask.call_args_list[1].args push_expected = yaml_load( PUSH_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), docker_secret="secret", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, scheduler=SCHEDULER_ID, service_name="test1", source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) push_expected["dependencies"].append(build_task_id) assert push_task == push_expected
def test_mark_rebuild_01(mocker): """test that "/force-rebuild" marks all services dirty""" root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.commit_message = "/force-rebuild" sched = Scheduler(evt, None, "group", "secret", "branch") sched.mark_services_for_rebuild() for svc in sched.services.values(): assert svc.dirty assert evt.list_changed_paths.call_count == 0
def test_github_tc(mocker, action, event, result, repo_args): """test github event parsing from taskcluster""" repo = mocker.patch("orion_decision.git.GitRepo") repo.return_value.message.return_value = "Test commit message" repo.return_value.git_call.return_value = 0 evt = GithubEvent.from_taskcluster(action, event) assert evt.repo is repo.return_value assert repo.call_args == repo_args assert repo.return_value.cleanup.call_count == 0 evt.cleanup() assert repo.return_value.cleanup.call_count == 1 for attr, value in result.items(): assert getattr(evt, attr) == value
def test_create_01(mocker): """test no task creation""" taskcluster = mocker.patch("orion_decision.scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) sched = Scheduler(evt, now, "group", "secret", "push") sched.create_tasks() assert queue.createTask.call_count == 0
def test_ci_create_01(mocker: MockerFixture) -> None: """test no CI task creation""" taskcluster = mocker.patch("orion_decision.ci_scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() evt = mocker.Mock( branch="dev", event_type="push", spec=GithubEvent(), ) mocker.patch("orion_decision.ci_scheduler.CIMatrix", autospec=True) sched = CIScheduler("test", evt, now, "group", {}) sched.create_tasks() assert queue.createTask.call_count == 0
def test_create_05(mocker: MockerFixture) -> None: """test no tasks are created for release event""" taskcluster = mocker.patch("orion_decision.scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.event_type = "release" sched = Scheduler(evt, now, "group", "secret", "push") sched.services["test1"].dirty = True sched.create_tasks() assert queue.createTask.call_count == 0
def test_create_06(mocker): """test no tasks are created for --dry-run""" taskcluster = mocker.patch("orion_decision.scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.event_type = "push" evt.commit = "commit" evt.branch = "push" evt.pull_request = None evt.clone_url = "https://example.com" sched = Scheduler(evt, now, "group", "secret", "push", dry_run=True) sched.services["test1"].dirty = True sched.create_tasks() assert queue.createTask.call_count == 0
def test_mark_rebuild_03(mocker): """test that "/force-rebuild=svc" marks some services dirty""" root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.commit_message = "/force-rebuild=test3,test6" evt.list_changed_paths.return_value = [ root / "recipes" / "linux" / "install.sh" ] sched = Scheduler(evt, None, "group", "secret", "branch") sched.mark_services_for_rebuild() assert evt.list_changed_paths.call_count == 1 assert sched.services["test1"].dirty assert sched.services["test2"].dirty assert sched.services["test3"].dirty assert sched.services["test4"].dirty assert not sched.services["test5"].dirty assert sched.services["test6"].dirty assert not sched.services["test7"].dirty
def test_create_09(mocker): """test recipe test task creation""" taskcluster = mocker.patch("orion_decision.scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() root = FIXTURES / "services03" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.commit = "commit" evt.branch = "main" evt.clone_url = "https://example.com" evt.pull_request = None sched = Scheduler(evt, now, "group", "secret", "push") sched.services["test5"].dirty = True sched.services["test6"].dirty = True sched.services.recipes["withdep.sh"].dirty = True sched.create_tasks() assert queue.createTask.call_count == 3 task1_id, task1 = queue.createTask.call_args_list[0].args assert task1 == yaml_load( BUILD_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), dockerfile="test5/Dockerfile", expires=stringDate(now + ARTIFACTS_EXPIRE), load_deps="0", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, route="index.project.fuzzing.orion.test5.main", scheduler=SCHEDULER_ID, service_name="test5", source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) task2_id, task2 = queue.createTask.call_args_list[1].args expected2 = yaml_load( RECIPE_TEST_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), dockerfile="services/test-recipes/Dockerfile", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, recipe_name="withdep.sh", scheduler=SCHEDULER_ID, source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) expected2["dependencies"].append(task1_id) assert task2 == expected2 _, task3 = queue.createTask.call_args_list[2].args expected3 = yaml_load( BUILD_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), dockerfile="test6/Dockerfile", expires=stringDate(now + ARTIFACTS_EXPIRE), load_deps="0", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, route="index.project.fuzzing.orion.test6.main", scheduler=SCHEDULER_ID, service_name="test6", source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) expected3["dependencies"].append(task2_id) assert task3 == expected3
def test_create_08(mocker, ci1_dirty, svc1_dirty, svc2_dirty, expected_image): """test "test" tasks creation with dirty ci image""" taskcluster = mocker.patch("orion_decision.scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() root = FIXTURES / "services06" evt = mocker.Mock(spec=GithubEvent()) evt.repo.path = root evt.repo.git = mocker.Mock(return_value="\n".join( str(p) for p in root.glob("**/*"))) evt.commit = "commit" evt.branch = "main" evt.fetch_ref = "fetch" evt.clone_url = "https://example.com" evt.pull_request = None sched = Scheduler(evt, now, "group", "secret", "push") sched.services["testci1"].dirty = ci1_dirty sched.services["svc1"].dirty = svc1_dirty sched.services["svc2"].dirty = svc2_dirty sched.create_tasks() assert queue.createTask.call_count == 3 if ci1_dirty else 2 call_idx = 0 if ci1_dirty: task1_id, task1 = queue.createTask.call_args_list[call_idx].args call_idx += 1 assert task1 == yaml_load( BUILD_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), dockerfile="testci1/Dockerfile", expires=stringDate(now + ARTIFACTS_EXPIRE), load_deps="0", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, route="index.project.fuzzing.orion.testci1.main", scheduler=SCHEDULER_ID, service_name="testci1", source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) svc = "svc1" if svc1_dirty else "svc2" expected2 = yaml_load( TEST_TASK.substitute( commit="commit", commit_url="https://example.com", deadline=stringDate(now + DEADLINE), dockerfile=f"{svc}/Dockerfile", expires=stringDate(now + ARTIFACTS_EXPIRE), max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, route=f"index.project.fuzzing.orion.{svc}.main", scheduler=SCHEDULER_ID, service_name=svc, source_url=SOURCE_URL, task_group="group", test_name=f"{svc}test", worker=WORKER_TYPE, )) if ci1_dirty: expected_image["taskId"] = task1_id expected2["dependencies"].append(task1_id) expected2["payload"]["image"] = expected_image sched.services[svc].tests[0].update_task(expected2, "https://example.com", "fetch", "commit", svc) task2_id, task2 = queue.createTask.call_args_list[call_idx].args call_idx += 1 assert task2 == expected2 task3_id, task3 = queue.createTask.call_args_list[call_idx].args call_idx += 1 expected3 = yaml_load( BUILD_TASK.substitute( clone_url="https://example.com", commit="commit", deadline=stringDate(now + DEADLINE), dockerfile=f"{svc}/Dockerfile", expires=stringDate(now + ARTIFACTS_EXPIRE), load_deps="0", max_run_time=int(MAX_RUN_TIME.total_seconds()), now=stringDate(now), owner_email=OWNER_EMAIL, provisioner=PROVISIONER_ID, route=f"index.project.fuzzing.orion.{svc}.main", scheduler=SCHEDULER_ID, service_name=svc, source_url=SOURCE_URL, task_group="group", worker=WORKER_TYPE, )) expected3["dependencies"].append(task2_id) assert task3 == expected3
def test_ci_create_02( mocker: MockerFixture, platform: str, matrix_secret: Optional[str], job_secret: Optional[str], ) -> None: """test single stage CI task creation""" taskcluster = mocker.patch("orion_decision.ci_scheduler.Taskcluster", autospec=True) queue = mocker.Mock() index = mocker.Mock() index.findTask.return_value = {"taskId": "msys-task"} taskcluster.get_service.side_effect = lambda x: { "index": index, "queue": queue }[x] now = datetime.utcnow() evt = mocker.Mock( branch="dev", event_type="push", ssh_url="ssh://repo", http_url="test://repo", fetch_ref="fetchref", repo_slug="project/test", tag=None, commit="commit", user="******", spec=GithubEvent(), ) mtx = mocker.patch("orion_decision.ci_scheduler.CIMatrix", autospec=True) job = MatrixJob( name="testjob", language="python", version="3.7", platform=platform, env={}, script=["test"], ) mtx.return_value.jobs = [job] secrets = [] scopes = [] clone_repo = evt.http_url def _create_secret(kind: str) -> CISecret: nonlocal clone_repo sec: CISecret if kind == "env": sec = CISecretEnv("project/test/token", "TOKEN") elif kind == "deploy": clone_repo = evt.ssh_url sec = CISecretKey("project/test/key") elif kind == "key": sec = CISecretKey("project/test/key", hostname="host") elif kind == "file": sec = CISecretFile("project/test/cfg", "/cfg") else: assert False, f"unknown secret kind: {kind}" scopes.append(f"secrets:get:{sec.secret}") return sec if job_secret is not None: sec = _create_secret(job_secret) job.secrets.append(sec) if matrix_secret is not None: sec = _create_secret(matrix_secret) secrets.append(sec) mtx.return_value.secrets = secrets sched = CIScheduler("test", evt, now, "group", {}) sched.create_tasks() assert queue.createTask.call_count == 1 _, task = queue.createTask.call_args[0] # add matrix secrets to `job`. this is different than how it's done in the # scheduler, but will have the same effect (and the scheduler is done with `job`) job.secrets.extend(secrets) kwds = { "ci_job": json_dump(str(job)), "clone_repo": clone_repo, "deadline": stringDate(now + DEADLINE), "fetch_ref": evt.fetch_ref, "fetch_rev": evt.commit, "http_repo": evt.http_url, "max_run_time": int(MAX_RUN_TIME.total_seconds()), "name": job.name, "now": stringDate(now), "project": "test", "provisioner": PROVISIONER_ID, "scheduler": SCHEDULER_ID, "task_group": "group", "user": evt.user, "worker": WORKER_TYPES[platform], } if platform == "linux": kwds["image"] = job.image else: assert index.findTask.call_count == 1 assert job.image in index.findTask.call_args[0][0] kwds["msys_task"] = "msys-task" expected = yaml_load(TEMPLATES[platform].substitute(**kwds)) expected["requires"] = "all-resolved" expected["scopes"].extend(scopes) if matrix_secret is not None or job_secret is not None: expected["payload"].setdefault("features", {}) expected["payload"]["features"]["taskclusterProxy"] = True assert set(task["scopes"]) == set(expected["scopes"]) assert len(task["scopes"]) == len(expected["scopes"]) task["scopes"] = expected["scopes"] assert task == expected assert all(sec.secret in task["payload"]["env"]["CI_JOB"] for sec in job.secrets)
def test_ci_create_03(mocker: MockerFixture, previous_pass: bool) -> None: """test two stage CI task creation""" taskcluster = mocker.patch("orion_decision.ci_scheduler.Taskcluster", autospec=True) queue = taskcluster.get_service.return_value now = datetime.utcnow() evt = mocker.Mock( branch="dev", event_type="push", http_url="test://repo", fetch_ref="fetchref", commit="commit", user="******", repo_slug="project/test", tag=None, spec=GithubEvent(), ) mtx = mocker.patch("orion_decision.ci_scheduler.CIMatrix", autospec=True) job1 = MatrixJob( name="testjob1", language="python", version="3.7", platform="linux", env={}, script=["test"], ) job2 = MatrixJob( name="testjob2", language="python", version="3.7", platform=job1.platform, env={}, script=["test"], stage=2, previous_pass=previous_pass, ) mtx.return_value.jobs = [job1, job2] mtx.return_value.secrets = [] sched = CIScheduler("test", evt, now, "group", {}) sched.create_tasks() assert queue.createTask.call_count == 2 task1_id, task1 = queue.createTask.call_args_list[0][0] kwds = { "ci_job": json_dump(str(job1)), "clone_repo": evt.http_url, "deadline": stringDate(now + DEADLINE), "fetch_ref": evt.fetch_ref, "fetch_rev": evt.commit, "http_repo": evt.http_url, "max_run_time": int(MAX_RUN_TIME.total_seconds()), "name": job1.name, "now": stringDate(now), "project": "test", "provisioner": PROVISIONER_ID, "scheduler": SCHEDULER_ID, "task_group": "group", "user": evt.user, "worker": WORKER_TYPES[job1.platform], } kwds["image"] = job1.image expected = yaml_load(TEMPLATES[job1.platform].substitute(**kwds)) expected["requires"] = "all-resolved" assert task1 == expected _, task2 = queue.createTask.call_args_list[1][0] kwds["ci_job"] = json_dump(str(job2)) kwds["image"] = job2.image kwds["name"] = job2.name kwds["worker"] = WORKER_TYPES[job2.platform] expected = yaml_load(TEMPLATES[job2.platform].substitute(**kwds)) if not previous_pass: expected["requires"] = "all-resolved" expected["dependencies"].append(task1_id) assert task2 == expected