From 0f526ca77472ad7bd90168a9dc4381582a542c62 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 7 Apr 2026 19:32:19 -0400 Subject: [PATCH] Simplify release process: remove intermediate PR step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: workflow_dispatch → build image + open release/N.N.N PR → approve production gate → PR merge → second job pins refs, tags, creates GitHub release. After: workflow_dispatch → approve production gate → build image, commit version bump directly to master, pin refs, tag, create GitHub release. One approval, no intermediate PR. --- .github/workflows/publish.yml | 6 +--- DEVGUIDE.md | 5 ++- bin/publish.py | 57 +++++++++++------------------------ 3 files changed, 21 insertions(+), 47 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fbc8c5bd..7836b46a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,17 +10,13 @@ on: - patch - minor - major - pull_request: - types: - - closed permissions: contents: write - pull-requests: write jobs: publish: runs-on: ubuntu-latest environment: production - if: github.event_name == 'workflow_dispatch' || (startsWith(github.event.pull_request.head.ref, 'release/') && github.event.pull_request.merged) + if: github.event_name == 'workflow_dispatch' steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 diff --git a/DEVGUIDE.md b/DEVGUIDE.md index d6d2e7e5..8c13d4db 100644 --- a/DEVGUIDE.md +++ b/DEVGUIDE.md @@ -82,9 +82,8 @@ When auto-tagging fails due to workflow file changes or other manual interventio 1. Merge PRs to master 2. Go to [publish.yml workflow](https://github.com/JuliaRegistries/TagBot/actions/workflows/publish.yml) -3. Run with desired version bump (major/minor/patch) — this builds and pushes the versioned Docker image (`ghcr.io/juliaregistries/tagbot:{version}`), updates `action.yml` with its SHA digest, and opens a release PR -4. Review and merge the created PR -5. CI tags the release, pushes floating Docker tags (`latest`, `{major}`, `{major}.{minor}`), and commits updated SHA pins to `example.yml`, `README.md`, and other doc files +3. Run with desired version bump (major/minor/patch) and approve the `production` environment gate +4. The workflow builds and pushes the versioned Docker image, commits the version bump to master, creates the Git tag and GitHub release, pushes floating Docker tags (`latest`, `{major}`, `{major}.{minor}`), and commits updated SHA pins to `example.yml`, `README.md`, and other doc files --- diff --git a/bin/publish.py b/bin/publish.py index a0d8f783..b8f163d2 100755 --- a/bin/publish.py +++ b/bin/publish.py @@ -10,7 +10,6 @@ from typing import List, Optional from github import Auth, Github, GithubException -from github.PullRequest import PullRequest from github.Repository import Repository from semver import VersionInfo @@ -47,22 +46,9 @@ def on_workflow_dispatch(version: str) -> None: update_pyproject_toml(semver) digest = build_and_push_versioned_image(semver) update_action_yml(semver, digest) - branch = git_push(semver) + release_sha = git_commit(semver) repo = GH.get_repo(REPO) - msg = f"Release {semver}" - repo.create_pull(title=msg, body=msg, head=branch, base="master") - - -def on_pull_request(number: int) -> None: - repo = GH.get_repo(REPO) - pr = repo.get_pull(number) - if not pr.merged or not pr.head.ref.startswith("release/"): - return - version = current_version() - tag_sha = pr.merge_commit_sha - git("fetch", "origin", "master") - git("checkout", "-B", "master", "origin/master") - update_action_ref_pins(version, tag_sha) + update_action_ref_pins(semver, release_sha) git("add", "--all") has_changes = ( subprocess.run( @@ -71,10 +57,10 @@ def on_pull_request(number: int) -> None: != 0 ) if has_changes: - git("commit", "--message", f"Pin action refs to v{version}") + git("commit", "--message", f"Pin action refs to v{semver}") git("push", "origin", "master") - update_tags(tag_sha) - create_release(repo, pr, tag_sha) + update_tags(release_sha) + create_release(repo, release_sha) push_floating_tags() @@ -125,13 +111,17 @@ def update_action_yml(version: VersionInfo, digest: str) -> None: f.write(updated) -def git_push(version: VersionInfo) -> str: - branch = f"release/{version}" - msg = f"Release {version}" - git("checkout", "-B", branch) - git("commit", "--all", "--message", msg) - git("push", "origin", "--force", branch) - return branch +def git_commit(version: VersionInfo) -> str: + """Commit the release changes to master and return the commit SHA.""" + git("commit", "--all", "--message", f"Release {version}") + git("push", "origin", "master") + result = subprocess.run( + ["git", "-C", WORKSPACE, "rev-parse", "HEAD"], + check=True, + capture_output=True, + text=True, + ) + return result.stdout.strip() def update_tags(commit: str) -> None: @@ -170,14 +160,13 @@ def update_action_ref_pins(version: VersionInfo, sha: str) -> None: f.write(updated) -def create_release(repo: Repository, pr: PullRequest, commit: str) -> None: - notes = get_release_notes(pr) +def create_release(repo: Repository, commit: str) -> None: release = "v" + str(current_version()) try: repo.create_git_release( tag=release, name=release, - message=notes, + message="", target_commitish=commit, generate_release_notes=True, ) @@ -188,14 +177,6 @@ def create_release(repo: Repository, pr: PullRequest, commit: str) -> None: raise -def get_release_notes(pr: PullRequest) -> str: - for comment in pr.get_issue_comments(): - m = re.search("(?si)Release notes:(.*)", comment.body) - if m: - return m[1].strip() - return "" - - def build_and_push_versioned_image(version: VersionInfo) -> str: tag = f"{DOCKER_IMAGE}:{version}" server = [DOCKER_IMAGE.split("/")[0]] if DOCKER_IMAGE.count("/") > 1 else [] @@ -257,5 +238,3 @@ def docker(*args: str, stdin: Optional[str] = None) -> None: event = json.load(f) if name == "workflow_dispatch": on_workflow_dispatch(event["inputs"]["bump"]) - elif name == "pull_request": - on_pull_request(event["pull_request"]["number"])