async def test_rules_conditions_schedule(): pulls = [ FakeQueuePullRequest({ "number": 1, "author": "me", "base": "main", "current-timestamp": date.utcnow(), "current-time": date.utcnow(), "current-day": date.Day(22), "current-month": date.Month(9), "current-year": date.Year(2021), "current-day-of-week": date.DayOfWeek(3), }), ] schema = voluptuous.Schema( voluptuous.All( [voluptuous.Coerce(rules.RuleConditionSchema)], voluptuous.Coerce(conditions.QueueRuleConditions), )) c = schema([ "base=main", "schedule=MON-FRI 08:00-17:00", "schedule=MONDAY-FRIDAY 10:00-12:00", "schedule=SAT-SUN 07:00-12:00", ]) await c(pulls) assert (c.get_summary() == """- [X] `base=main` - [X] `schedule=MON-FRI 08:00-17:00` - [ ] `schedule=MONDAY-FRIDAY 10:00-12:00` - [ ] `schedule=SAT-SUN 07:00-12:00` """)
async def test_rules_checks_status_regex(): pull = FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "main", "head": "feature-1", "check-success": [], "check-failure": [], "check-pending": [], "check-neutral": [], "check-skipped": [], "check-stale": [], }) conds = ["check-success~=^ci-1$", "check-success~=^ci-2$"] # Nothing reported await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Pending reported pull.attrs["check-pending"] = ["ci-1"] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["ci-2"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Failure reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = ["ci-1"] pull.attrs["check-success"] = ["ci-2"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # Success reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["ci-1", "ci-2"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS) # half reported success pull.attrs["check-failure"] = [] pull.attrs["check-pending"] = [] pull.attrs["check-success"] = ["ci-1"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # half reported failure, fail early pull.attrs["check-failure"] = ["ci-1"] pull.attrs["check-pending"] = [] pull.attrs["check-success"] = [] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE)
def get_scheduled_pr() -> FakePR: return FakePR( { "current-day-of-week": date.DayOfWeek(date.utcnow().isoweekday()), "current-year": date.Year(date.utcnow().year), "current-day": date.Day(date.utcnow().day), "number": 3433, "current-time": date.utcnow(), "current-month": date.Month(date.utcnow().month), } )
async def test_rules_checks_basic(logger_checker): pull = FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "main", "head": "feature-1", "label": [], "check-success": [], "check-neutral": [], "check-failure": [], "check-pending": [], "check-skipped": [], "check-stale": [], }) conds = ["check-success=fake-ci", "label=foobar"] # Label missing and nothing reported await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Label missing and success pull.attrs["check-success"] = ["fake-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # label ok and nothing reported pull.attrs["label"] = ["foobar"] pull.attrs["check-success"] = [] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Pending reported pull.attrs["check-pending"] = ["fake-ci"] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["test-starter"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Failure reported pull.attrs["check-pending"] = ["whatever"] pull.attrs["check-failure"] = ["foo", "fake-ci"] pull.attrs["check-success"] = ["test-starter"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # Success reported pull.attrs["check-pending"] = ["whatever"] pull.attrs["check-failure"] = ["foo"] pull.attrs["check-success"] = ["fake-ci", "test-starter"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS)
async def test_rules_checks_status_with_negative_conditions3(logger_checker): pull = FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "main", "head": "feature-1", "check-success": [], "check-failure": [], "check-pending": [], "check-neutral": [], "check-skipped": [], "check-stale": [], }) conds = [ "check-success=test-starter", "#check-pending=0", "#check-failure=0", ] # Nothing reported await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Pending reported pull.attrs["check-pending"] = ["foo"] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["test-starter"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Failure reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = ["foo"] pull.attrs["check-success"] = ["test-starter"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # Success reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["test-starter", "foo"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS) # half reported, sorry..., UNDEFINED BEHAVIOR pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["test-starter"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS)
async def test_rules_conditions_update() -> None: pulls = [ FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "main", "head": "feature-1", "label": ["foo", "bar"], "check-success": ["tests"], "check-pending": [], # type: ignore "check-failure": ["jenkins/fake-tests"], "check-skipped": [], # type: ignore "check-stale": [], # type: ignore }), ] pulls[0].sync_checks() schema = voluptuous.Schema( voluptuous.All( [voluptuous.Coerce(rules.RuleConditionSchema)], voluptuous.Coerce(conditions.QueueRuleConditions), )) c = schema([ "label=foo", "check-success=tests", "check-success=jenkins/fake-tests", ]) await c(pulls) assert (c.get_summary() == """- `label=foo` - [X] #1 - [X] `check-success=tests` - [ ] `check-success=jenkins/fake-tests` """) state = await checks_status.get_rule_checks_status( mock.Mock(), FAKE_REPO, typing.cast(typing.List[context.BasePullRequest], pulls), mock.Mock(conditions=c), ) assert state == check_api.Conclusion.FAILURE
async def test_rules_checks_status_ceph(logger_checker): pull = FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "devel", "head": "feature-1", "check-failure": [], "check-neutral": [], "check-skipped": [], "check-stale": [], "approved-reviews-by": ["me", "other"], "changes-requested-reviews-by": [], "label": ["mergeit"], "check-success": ["Summary", "DCO", "build"], "check-success-or-neutral": ["Summary", "DCO", "build"], "check-success-or-neutral-or-pending": [ "Summary", "DCO", "golangci-lint", "commitlint", "build", "codespell", "multi-arch-build", "go-test", "lint-extras", "mod-check", "go-test-api", "Rule: automatic merge (merge)", "ci/centos/mini-e2e/k8s-1.20", "ci/centos/upgrade-tests-rbd", "ci/centos/mini-e2e-helm/k8s-1.22", "ci/centos/upgrade-tests-cephfs", "ci/centos/mini-e2e/k8s-1.22", "ci/centos/k8s-e2e-external-storage/1.22", "ci/centos/mini-e2e-helm/k8s-1.21", "ci/centos/k8s-e2e-external-storage/1.21", "ci/centos/mini-e2e/k8s-1.21", "ci/centos/mini-e2e-helm/k8s-1.20", ], "status-success": ["Summary", "DCO", "build"], "check-pending": [ "golangci-lint", "commitlint", "codespell", "multi-arch-build", "go-test", "lint-extras", "mod-check", "go-test-api", "Rule: automatic merge (merge)", "ci/centos/mini-e2e/k8s-1.20", "ci/centos/upgrade-tests-rbd", "ci/centos/mini-e2e-helm/k8s-1.22", "ci/centos/upgrade-tests-cephfs", "ci/centos/mini-e2e/k8s-1.22", "ci/centos/k8s-e2e-external-storage/1.22", "ci/centos/mini-e2e-helm/k8s-1.21", "ci/centos/k8s-e2e-external-storage/1.21", "ci/centos/mini-e2e/k8s-1.21", "ci/centos/mini-e2e-helm/k8s-1.20", ], }) pull.attrs["check"] = (pull.attrs.get("check-success", []) + pull.attrs.get("check-neutral", []) + pull.attrs.get("check-pending", []) + pull.attrs.get("check-stale", []) + pull.attrs.get("check-failure", []) + pull.attrs.get("check-skipped", [])) tree = { "and": [ { "!=": ["label", "DNM"] }, { "~=": ["base", "^(devel)|(release-.+)$"] }, { ">=": ["#approved-reviews-by", 2] }, { "=": ["approved-reviews-by", "@ceph/ceph-csi-maintainers"] }, { "=": ["#changes-requested-reviews-by", 0] }, { "=": ["status-success", "codespell"] }, { "=": ["status-success", "multi-arch-build"] }, { "=": ["status-success", "go-test"] }, { "=": ["status-success", "golangci-lint"] }, { "=": ["status-success", "commitlint"] }, { "=": ["status-success", "mod-check"] }, { "=": ["status-success", "lint-extras"] }, { "=": ["status-success", "ci/centos/k8s-e2e-external-storage/1.21"] }, { "=": ["status-success", "ci/centos/k8s-e2e-external-storage/1.22"] }, { "=": ["status-success", "ci/centos/mini-e2e-helm/k8s-1.20"] }, { "=": ["status-success", "ci/centos/mini-e2e-helm/k8s-1.21"] }, { "=": ["status-success", "ci/centos/mini-e2e-helm/k8s-1.22"] }, { "=": ["status-success", "ci/centos/mini-e2e/k8s-1.20"] }, { "=": ["status-success", "ci/centos/mini-e2e/k8s-1.21"] }, { "=": ["status-success", "ci/centos/mini-e2e/k8s-1.22"] }, { "=": ["status-success", "ci/centos/upgrade-tests-cephfs"] }, { "=": ["status-success", "ci/centos/upgrade-tests-rbd"] }, { "=": ["status-success", "DCO"] }, ] } f = filter.IncompleteChecksFilter( tree, pending_checks=pull.attrs["check-pending"], all_checks=pull.attrs["check"]) async def fake_get_team_members(*args): return ["me", "other", "foo", "bar"] repo_with_team = mock.Mock( repo={"owner": { "login": "******" }}, installation=mock.Mock(get_team_members=mock.Mock( side_effect=fake_get_team_members)), ) live_resolvers.configure_filter(repo_with_team, f) assert await f(pull) == filter.IncompleteCheck
async def test_rules_checks_status_depop(logger_checker): pull = FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "main", "head": "feature-1", "check-success": [], "check-failure": [], "check-pending": [], "check-neutral": [], "check-skipped": [], "check-stale": [], "approved-reviews-by": ["me"], "changes-requested-reviews-by": [], "label": ["mergeit"], }) conds = [ "check-success=Summary", "check-success=c-ci/status", "check-success=c-ci/s-c-t", "check-success=c-ci/c-p-validate", "#approved-reviews-by>=1", "approved-reviews-by=me", "-label=flag:wait", { "or": [ "check-success=c-ci/status", "check-neutral=c-ci/status", "check-skipped=c-ci/status", ] }, { "or": [ "check-success=c-ci/s-c-t", "check-neutral=c-ci/s-c-t", "check-skipped=c-ci/s-c-t", ] }, { "or": [ "check-success=c-ci/c-p-validate", "check-neutral=c-ci/c-p-validate", "check-skipped=c-ci/c-p-validate", ] }, "#approved-reviews-by>=1", "#changes-requested-reviews-by=0", ] # Nothing reported await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Pending reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = [ "Summary", "continuous-integration/jenkins/pr-head" ] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Pending reported pull.attrs["check-pending"] = ["c-ci/status"] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = [ "Summary", "continuous-integration/jenkins/pr-head", "c-ci/s-c-t", ] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Pending reported pull.attrs["check-pending"] = [ "c-ci/status", "c-ci/s-c-t", "c-ci/c-p-validate", ] pull.attrs["check-failure"] = ["c-ci/g-validate"] pull.attrs["check-success"] = ["Summary"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Failure reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = [ "c-ci/s-c-t", "c-ci/g-validate", ] pull.attrs["check-success"] = [ "Summary", "c-ci/status", "c-ci/c-p-validate", ] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # Success reported pull.attrs["check-pending"] = [] pull.attrs["check-failure"] = ["c-ci/g-validate"] pull.attrs["check-success"] = [ "Summary", "c-ci/status", "c-ci/s-c-t", "c-ci/c-p-validate", ] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS)
async def test_rules_checks_with_and_or(logger_checker): pull = FakeQueuePullRequest({ "number": 1, "current-year": date.Year(2018), "author": "me", "base": "main", "head": "feature-1", "label": [], "check-success": [], "check-failure": [], "check-pending": [], "check-neutral": [], "check-skipped": [], "check-stale": [], }) conds = [ { "or": ["check-success=fake-ci", "label=skip-tests"] }, "check-success=other-ci", ] # Label missing and nothing reported await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Label missing and half success pull.attrs["check-success"] = ["fake-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Label missing and half success and half pending pull.attrs["check-success"] = ["fake-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # Label missing and all success pull.attrs["check-success"] = ["fake-ci", "other-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS) # Label missing and half failure pull.attrs["check-success"] = ["fake-ci"] pull.attrs["check-failure"] = ["other-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # Label missing and half failure bus pull.attrs["check-success"] = ["other-ci"] pull.attrs["check-failure"] = ["fake-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # label ok and nothing reported pull.attrs["label"] = ["skip-tests"] pull.attrs["check-success"] = [] pull.attrs["check-failure"] = [] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # label ok and failure pull.attrs["label"] = ["skip-tests"] pull.attrs["check-success"] = [] pull.attrs["check-failure"] = ["other-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.FAILURE) # label ok and failure pull.attrs["label"] = ["skip-tests"] pull.attrs["check-success"] = [] pull.attrs["check-failure"] = ["fake-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.PENDING) # label ok and success pull.attrs["label"] = ["skip-tests"] pull.attrs["check-pending"] = ["fake-ci"] pull.attrs["check-failure"] = [] pull.attrs["check-success"] = ["other-ci"] await assert_queue_rule_checks_status(conds, pull, check_api.Conclusion.SUCCESS)
date.Time(10, 0, tzinfo=zoneinfo.ZoneInfo("PST8PDT")), ) }, ), ( "current-time>=10:00", { ">=": ( "current-time", date.Time(10, 0, tzinfo=datetime.timezone.utc), ) }, ), ("current-day=4", {"=": ("current-day", date.Day(4))}), ("current-month=5", {"=": ("current-month", date.Month(5))}), ("current-year=2000", {"=": ("current-year", date.Year(2000))}), ("current-day-of-week=4", {"=": ("current-day-of-week", date.DayOfWeek(4))}), ("current-day-of-week=MON", {"=": ("current-day-of-week", date.DayOfWeek(1))}), ( "current-day-of-week=WednesDay", {"=": ("current-day-of-week", date.DayOfWeek(3))}, ), ("current-day-of-week=sun", {"=": ("current-day-of-week", date.DayOfWeek(7))}), ( "schedule: MON-FRI 08:00-17:00", { "@": ( "schedule", { "and": ( {
async def test_year_near_datetime() -> None: with freeze_time("2012-01-14T12:15:00", tz_offset=0) as frozen_time: today = frozen_time().replace(tzinfo=UTC) in_2016 = datetime.datetime(2016, 1, 1, 0, 0, 0, 0, tzinfo=UTC) in_2017 = datetime.datetime(2017, 1, 1, 0, 0, 0, 0, tzinfo=UTC) f = filter.NearDatetimeFilter({"<=": ("foo", date.Year(2016))}) frozen_time.move_to(today.replace(year=2016)) assert await f(FakePR({"foo": date.Year(2016)})) == in_2017 frozen_time.move_to(today.replace(year=2017)) assert await f(FakePR({"foo": date.Year(2017)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2011)) assert await f(FakePR({"foo": date.Year(2011)})) == in_2016 assert await f(FakePR({"foo": None})) == date.DT_MAX f = filter.NearDatetimeFilter({"<": ("foo", date.Year(2016))}) frozen_time.move_to(today.replace(year=2016)) assert await f(FakePR({"foo": date.Year(2016)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2017)) assert await f(FakePR({"foo": date.Year(2017)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2011)) assert await f(FakePR({"foo": date.Year(2011)})) == in_2016 assert await f(FakePR({"foo": None})) == date.DT_MAX f = filter.NearDatetimeFilter({"<=": ("foo", date.Year(2016))}) frozen_time.move_to(today.replace(year=2016)) assert await f(FakePR({"foo": date.Year(2016)})) == in_2017 frozen_time.move_to(today.replace(year=2017)) assert await f(FakePR({"foo": date.Year(2017)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2011)) assert await f(FakePR({"foo": date.Year(2011)})) == in_2016 assert await f(FakePR({"foo": None})) == date.DT_MAX f = filter.NearDatetimeFilter({"<": ("foo", date.Year(2016))}) frozen_time.move_to(today.replace(year=2016)) assert await f(FakePR({"foo": date.Year(2016)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2017)) assert await f(FakePR({"foo": date.Year(2017)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2011)) assert await f(FakePR({"foo": date.Year(2011)})) == in_2016 assert await f(FakePR({"foo": None})) == date.DT_MAX f = filter.NearDatetimeFilter({"=": ("foo", date.Year(2016))}) frozen_time.move_to(today.replace(year=2016)) assert await f(FakePR({"foo": date.Year(2016)})) == in_2017 frozen_time.move_to(today.replace(year=2017)) assert await f(FakePR({"foo": date.Year(2017)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2011)) assert await f(FakePR({"foo": date.Year(2011)})) == in_2016 assert await f(FakePR({"foo": None})) == date.DT_MAX f = filter.NearDatetimeFilter({"!=": ("foo", date.Year(2016))}) frozen_time.move_to(today.replace(year=2016)) assert await f(FakePR({"foo": date.Year(2016)})) == in_2017 frozen_time.move_to(today.replace(year=2017)) assert await f(FakePR({"foo": date.Year(2017)})) == date.DT_MAX frozen_time.move_to(today.replace(year=2011)) assert await f(FakePR({"foo": date.Year(2011)})) == in_2016 assert await f(FakePR({"foo": None})) == date.DT_MAX
async def test_partial_datetime_year_str() -> None: assert "foo>=2005" == str(filter.BinaryFilter({">=": ("foo", date.Year(2005))})) assert "foo<=2004" == str(filter.BinaryFilter({"<=": ("foo", date.Year(2004))})) assert "foo=2003" == str(filter.BinaryFilter({"=": ("foo", date.Year(2003))}))
assert "foo<=4" == str(filter.BinaryFilter({"<=": ("foo", klass(4))})) assert "foo=3" == str(filter.BinaryFilter({"=": ("foo", klass(3))})) async def test_partial_datetime_year_str() -> None: assert "foo>=2005" == str(filter.BinaryFilter({">=": ("foo", date.Year(2005))})) assert "foo<=2004" == str(filter.BinaryFilter({"<=": ("foo", date.Year(2004))})) assert "foo=2003" == str(filter.BinaryFilter({"=": ("foo", date.Year(2003))})) @pytest.mark.parametrize( "klass", ( date.Day, date.Month, lambda n: date.Year(2000 + n), date.DayOfWeek, ), ) @freeze_time("2012-01-14") async def test_partial_datetime_binary( klass: typing.Type[date.PartialDatetime], ) -> None: f = filter.BinaryFilter({"<=": ("foo", klass(5))}) assert await f(FakePR({"foo": klass(2)})) assert await f(FakePR({"foo": klass(5)})) assert not await f(FakePR({"foo": klass(7)})) f = filter.BinaryFilter({"=": ("foo", klass(5))}) assert await f(FakePR({"foo": klass(5)}))