diff --git a/forgetest/forgetest/campaign.py b/forgetest/forgetest/campaign.py index 6514693..94b1fdc 100644 --- a/forgetest/forgetest/campaign.py +++ b/forgetest/forgetest/campaign.py @@ -70,6 +70,18 @@ def compute(records, tests, manifest, catalog_hash, running=None): campaign, last, closed_by, invalidate = open_campaign(records, manifest.content_sha, catalog_hash) epoch = invalidate.get("ts") if invalidate else None open_id = campaign.get("id") if campaign else None + # The invalidate record keeps its epoch for good: nothing older than it + # inherits. The page and the artifact report it only while it still asks + # for something, that is until a campaign has started after it. + invalidate_shown = invalidate + if invalidate: + seen = False + for r in records: + if r is invalidate: + seen = True + elif seen and r.get("t") == "campaign": + invalidate_shown = None + break by_test = {} for r in results: @@ -151,7 +163,7 @@ def compute(records, tests, manifest, catalog_hash, running=None): "campaign": campaign, "last_campaign": last, "closed_by": closed_by, - "invalidate": invalidate, + "invalidate": invalidate_shown, "authorized": authorized, "counts": counts, "tests": out_tests, diff --git a/forgetest/tests/test_campaign.py b/forgetest/tests/test_campaign.py index d8b5195..74b5f71 100644 --- a/forgetest/tests/test_campaign.py +++ b/forgetest/tests/test_campaign.py @@ -157,10 +157,18 @@ class CampaignTests(unittest.TestCase): self.assertNotEqual(st["tests"][t.id]["status"], "inherited") # after the invalidate, a new campaign's passes count and later ones inherit again recs.append(rec_campaign("c2", self.man, self.chash, "2026-08-22T10:00:00Z")) + st = self.compute(recs) + # the campaign that started after it answers the invalidation: the + # page no longer announces it, while its epoch still holds + self.assertIsNone(st["invalidate"]) + for t in self.tests: + self.assertTrue(st["tests"][t.id]["required"], t.id) + self.assertNotEqual(st["tests"][t.id]["status"], "inherited") for i, t in enumerate(self.tests): recs.append(rec_result("c2", t, self.man, "PASS", "2026-08-22T10:0%d:00Z" % (i + 1))) st = self.compute(recs) self.assertTrue(st["authorized"]) + self.assertIsNone(st["invalidate"]) def test_reset_and_catalog_change(self): recs = [rec_campaign("c1", self.man, self.chash, "2026-08-20T10:00:00Z"),