Skip to content

Commit a00ac1b

Browse files
committed
fix: Improve release progress tracking and publication links.
- Ensure the 'Preparation' checkbox is correctly checked in CI by using the repository owner instead of the actor for PR identification. - Use the dynamic draft release URL from GitHub for the publication instruction link.
1 parent 49d2aac commit a00ac1b

3 files changed

Lines changed: 82 additions & 6 deletions

File tree

tools/create_release.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ def compute_done_milestones(self, version: str) -> set[str]:
149149

150150
# 1. Preparation
151151
if self.github.find_pr_for_branch(
152-
f"{self.github.actor()}:{BRANCH_PREFIX}/{version}", self.config.main_branch
152+
f"{self.git.owner('origin')}:{BRANCH_PREFIX}/{version}",
153+
self.config.main_branch,
153154
):
154155
done.add("Preparation")
155156

@@ -888,12 +889,14 @@ def stage_publish_release(self, version: str) -> None:
888889
return
889890
if self.config.github_actions:
890891
s.ok("Asking user to publish the release")
892+
release = self.github.release(version)
893+
url = release["html_url"]
891894
raise self.assign_to_user(
892895
s,
893896
version,
894897
task="Publication",
895898
action="publish the release",
896-
instruction=f"All checks passed and assets signed. Please [publish the release](https://github.com/{self.github.repository()}/releases/tag/{version}) manually.",
899+
instruction=f"All checks passed and assets signed. Please [publish the release]({url}) manually.",
897900
)
898901
s.ok("Not implemented yet")
899902

tools/lib/github.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,20 @@ def release_id(self, tag: str) -> int:
335335
return rid
336336
raise ValueError(f"Release {tag} not found in {self.repository()}")
337337

338+
def get_release(self, tag: str) -> Any:
339+
"""Get the full release object for a tag, or None if not found."""
340+
rid = self.get_release_id(tag)
341+
if rid is None:
342+
return None
343+
return self.api_uncached(f"/repos/{self.repository()}/releases/{rid}")
344+
345+
def release(self, tag: str) -> Any:
346+
"""Get the full release object for a tag."""
347+
release = self.get_release(tag)
348+
if release is not None:
349+
return release
350+
raise ValueError(f"Release {tag} not found in {self.repository()}")
351+
338352
def actor(self) -> str:
339353
"""Returns the GitHub username for the current repository."""
340354
github_actor = os.getenv("GITHUB_ACTOR")

tools/release_e2e_test.py

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ def api_post(
9595
params: dict[str, Any] | None = None,
9696
) -> Any:
9797
if url.endswith("/pulls"):
98+
head_user, head_ref = (
99+
json["head"].split(":", 1)
100+
if ":" in json["head"]
101+
else ("toktok-releaser", json["head"])
102+
)
98103
pr = {
99104
"title": json["title"],
100105
"body": json["body"],
@@ -104,7 +109,11 @@ def api_post(
104109
"node_id": f"node{len(self._prs)}",
105110
"html_url": f"url{len(self._prs)}",
106111
"state": "open",
107-
"head": {"sha": "sha123", "ref": json["head"]},
112+
"head": {
113+
"sha": "sha123",
114+
"ref": head_ref,
115+
"user": {"login": head_user},
116+
},
108117
"milestone": None,
109118
"draft": json.get("draft", False),
110119
"merged_at": None,
@@ -123,6 +132,7 @@ def api_post(
123132
"prerelease": json["prerelease"],
124133
"draft": json["draft"],
125134
"published_at": None,
135+
"html_url": f"https://github.com/TokTok/ci-tools/releases/edit/{json['tag_name']}",
126136
}
127137
self._releases.append(release)
128138
return release
@@ -217,7 +227,8 @@ def find_pr_for_branch(
217227
) -> github.PullRequest | None:
218228
for pr_data in self._prs:
219229
if pr_data["state"] == state or state == "all":
220-
if pr_data["head"]["ref"] == head.split(":")[-1]:
230+
pr_head = f"{pr_data['head']['user']['login']}:{pr_data['head']['ref']}"
231+
if pr_head == head:
221232
return github.PullRequest.fromJSON(pr_data)
222233
return None
223234

@@ -312,7 +323,7 @@ def checkout(self, name: str) -> None:
312323
self._current_branch = name
313324

314325
def owner(self, remote: str) -> str:
315-
return "bot"
326+
return "human"
316327

317328
def last_commit_message(self, branch: str) -> str:
318329
return self._log[-1] if self._log else ""
@@ -415,6 +426,7 @@ def test_full_release_lifecycle(self) -> None:
415426
"tag_name": "v1.0.0",
416427
"published_at": None,
417428
"body": "Existing draft notes",
429+
"html_url": "https://github.com/TokTok/ci-tools/releases/edit/v1.0.0",
418430
}
419431
)
420432

@@ -487,11 +499,16 @@ def mock_action_runs(branch: str, sha: str) -> list[github.ActionRun]:
487499
pass
488500

489501
# Verify intermediate dashboard state
502+
self.assertIn("[x] Create release branch and PR", gh._issues[1]["body"])
490503
self.assertIn("**Current Step: Finalize release**", gh._issues[1]["body"])
491504
self.assertIn(
492505
"Action Required:** All checks passed and assets signed",
493506
gh._issues[1]["body"],
494507
)
508+
self.assertIn(
509+
"https://github.com/TokTok/ci-tools/releases/edit/v1.0.0",
510+
gh._issues[1]["body"],
511+
)
495512

496513
# Simulate user published release, re-assign bot, and re-run
497514
gh._releases[0]["published_at"] = "2026-02-06T00:00:00Z"
@@ -503,6 +520,41 @@ def mock_action_runs(branch: str, sha: str) -> list[github.ActionRun]:
503520
self.assertEqual(gh._issues[1]["state"], "closed")
504521
self.assertIn("[x] Finalize release", gh._issues[1]["body"])
505522

523+
def test_mismatched_actor_and_owner(self) -> None:
524+
"""Verify that the dashboard works when actor and owner are different."""
525+
config = self.make_config()
526+
gh = FakeGitHub()
527+
gh._user = {"login": "releaser-bot"}
528+
gh.add_issue(
529+
1,
530+
"Release tracking issue",
531+
"### Release notes\nCool notes\nProduction release",
532+
)
533+
gh.add_milestone(1, "v1.0.0")
534+
535+
gt = FakeGit()
536+
537+
# Simulate owner being different from actor
538+
def mock_owner(remote: str) -> str:
539+
return "TokTok"
540+
541+
setattr(gt, "owner", mock_owner)
542+
543+
releaser = Releaser(config, gt, gh)
544+
545+
with self.release_mocks(gh, gt):
546+
# We only care about the preparation stage for this test
547+
releaser.stage_init()
548+
version = releaser.stage_version()
549+
releaser.stage_branch(version)
550+
releaser.stage_pull_request(version)
551+
releaser.update_dashboard(version)
552+
553+
# Check that the checkbox is marked
554+
self.assertIn("[x] Create release branch and PR", gh._issues[1]["body"])
555+
# Verify the PR head in our fake storage
556+
self.assertEqual(gh._prs[0]["head"]["user"]["login"], "TokTok")
557+
506558
def test_invalid_issue_title(self) -> None:
507559
config = self.make_config()
508560
gh = FakeGitHub()
@@ -528,6 +580,7 @@ def test_prerelease_lifecycle(self) -> None:
528580
"published_at": "2026-02-06T00:00:00Z",
529581
"prerelease": True,
530582
"draft": False,
583+
"html_url": "https://github.com/TokTok/ci-tools/releases/edit/v1.0.0-rc.1",
531584
}
532585
)
533586

@@ -578,7 +631,11 @@ def test_existing_pr_update(self) -> None:
578631
"node_id": "node555",
579632
"html_url": "url555",
580633
"state": "open",
581-
"head": {"sha": "sha123", "ref": "release/v1.0.0"},
634+
"head": {
635+
"sha": "sha123",
636+
"ref": "release/v1.0.0",
637+
"user": {"login": "human"},
638+
},
582639
"milestone": {"number": 1},
583640
"draft": True,
584641
"merged_at": None,
@@ -660,6 +717,7 @@ def test_release_ci_failure(self) -> None:
660717
"tag_name": "v1.0.0",
661718
"published_at": None,
662719
"body": "Existing draft notes",
720+
"html_url": "https://github.com/TokTok/ci-tools/releases/edit/v1.0.0",
663721
}
664722
)
665723

@@ -698,6 +756,7 @@ def test_release_ci_timeout(self) -> None:
698756
"tag_name": "v1.0.0",
699757
"published_at": None,
700758
"body": "Existing draft notes",
759+
"html_url": "https://github.com/TokTok/ci-tools/releases/edit/v1.0.0",
701760
}
702761
)
703762

0 commit comments

Comments
 (0)