assertProjectUnchanged fails if any row in the `before` snapshot went missing or got mutated in `after`. Keyed by resource name (unique per project by construction) so comparison is order-insensitive. Issue.UpdateTime is deliberately NOT compared — the approval runner actively updates open issues i
( t *testing.T, before, after *projectSnapshot, label string, )
| 641 | // behavior, not a cross-project leak. Title and Status are the fields a |
| 642 | // cross-project corruption would mutate. |
| 643 | func assertProjectUnchanged( |
| 644 | t *testing.T, |
| 645 | before, after *projectSnapshot, |
| 646 | label string, |
| 647 | ) { |
| 648 | t.Helper() |
| 649 | a := require.New(t) |
| 650 | |
| 651 | assertNoChange(t, before.Plans, after.Plans, |
| 652 | func(p *v1pb.Plan) string { return p.Name }, |
| 653 | func(b, af *v1pb.Plan) { |
| 654 | a.True(proto.Equal(b.UpdateTime, af.UpdateTime), "%s: plan %s update_time changed", label, b.Name) |
| 655 | }, |
| 656 | label, "plan") |
| 657 | |
| 658 | assertNoChange(t, before.Issues, after.Issues, |
| 659 | func(i *v1pb.Issue) string { return i.Name }, |
| 660 | func(b, af *v1pb.Issue) { |
| 661 | a.Equal(b.Title, af.Title, "%s: issue %s title changed", label, b.Name) |
| 662 | a.Equal(b.Status, af.Status, "%s: issue %s status changed", label, b.Name) |
| 663 | }, |
| 664 | label, "issue") |
| 665 | |
| 666 | assertNoChange(t, before.TaskRuns, after.TaskRuns, |
| 667 | func(tr *v1pb.TaskRun) string { return tr.Name }, |
| 668 | func(b, af *v1pb.TaskRun) { |
| 669 | a.Equal(b.Status, af.Status, "%s: task_run %s status changed from %v to %v", label, b.Name, b.Status, af.Status) |
| 670 | a.True(proto.Equal(b.UpdateTime, af.UpdateTime), "%s: task_run %s update_time changed", label, b.Name) |
| 671 | }, |
| 672 | label, "task_run") |
| 673 | |
| 674 | assertNoChange(t, before.PlanCheckRuns, after.PlanCheckRuns, |
| 675 | func(p *v1pb.PlanCheckRun) string { return p.Name }, |
| 676 | func(b, af *v1pb.PlanCheckRun) { |
| 677 | a.Equal(b.Status, af.Status, "%s: plan_check_run %s status changed from %v to %v", label, b.Name, b.Status, af.Status) |
| 678 | }, |
| 679 | label, "plan_check_run") |
| 680 | |
| 681 | // issue_comment is keyed by composite (project, id); a cross-project |
| 682 | // emission would surface here as either a new row in `after` or a |
| 683 | // disappeared row. |
| 684 | assertNoChange(t, before.IssueComments, after.IssueComments, |
| 685 | func(c *v1pb.IssueComment) string { return c.Name }, |
| 686 | func(b, af *v1pb.IssueComment) { |
| 687 | a.Equal(b.Comment, af.Comment, "%s: issue_comment %s comment changed", label, b.Name) |
| 688 | }, |
| 689 | label, "issue_comment") |
| 690 | } |
| 691 | |
| 692 | // assertNoChange compares two row slices keyed by name, fails if any |
| 693 | // row disappeared, appeared, or duplicated. Per-row equality beyond |
no test coverage detected