Skip to content

refactor(cicd): share the GitHub transport between the two release scripts - #37387

Open
sfreudenthaler wants to merge 1 commit into
mainfrom
refactor-share-release-github
Open

refactor(cicd): share the GitHub transport between the two release scripts#37387
sfreudenthaler wants to merge 1 commit into
mainfrom
refactor-share-release-github

Conversation

@sfreudenthaler

Copy link
Copy Markdown
Member

Closes: #37382

Note

#37369 stacks on top of this one. #37361 (the fix this came out of) is already merged.

Why

release-qa-status was forked from gather-release-data and still carries a verbatim copy of its GitHub transport. Since the fork, every maintenance change to that layer has had to patch both copies:

Commit Change Both files?
bf4c4c7 (#35028) created gather-release-data
2825aff (#37140) fix for #37138 — draft releases / undocumented tags
02e9601 (#37213) fix for #37201 — the (#N) squash-subject regex

Two for two, and both were duplicated bugs: same defect, shipped twice, found twice, fixed twice.

The original author saw it coming. release-qa-status/src/github.ts opens with:

"Mirrors the patterns in .github/scripts/gather-release-data/src/github.ts so the two tools stay easy to consolidate later."

This is later.

What moved — ~184 lines, verbatim

Function Lines Difference between the copies
resolvePRNumbers 58 none
fetchCommitRange 46 comment placement
listStandardReleaseTags 22 none
onThrottle 19 none
createOctokit 15 one error-message string
findPreviousTag 11 brace style
parseRepo 7 none
CommitInfo, ReleaseRef 6 none

What deliberately did not move

fetchPRDetails. Same name, different product: the QA report needs url / author / authorType / externalRefs; the changelog needs a truncated body and no author. Merging them means a union return type with each caller ignoring half of it.

categorize, qa, exclusions, format and both index.ts are untouched. The cut is transport vs. domain — nearly the boundary the file layout already implied.

One test deleted rather than moved

release-qa-status/src/github.test.ts existed solely to assert its findPreviousTag matched the other copy's:

"Guards against drift from gather-release-data/src/github.ts, which resolves the same release boundary. If these two disagree, the QA status and the changelog report on different commit ranges for the same release."

A test that guards against drift between two copies is obsolete once there is one copy. Its three cases are already covered in shared/github.test.ts.

Mechanics

  • npm workspaces at .github/scripts/ — one install, one lockfile instead of two, and @octokit/* resolves from the shared module.
  • Consumers import ../../shared/github by relative path, so there is no build-ordering step between packages.
  • gather-release-data now runs through ts-node, which release-qa-status already did. That drops a build step from the release-notes workflow and removes the rootDir constraint that otherwise blocks importing ../shared. tsc --noEmit stays as a type-check gate, so nothing is lost.

Verification

  • gather-release-data over v26.08.24-01...v26.09.02-01 (485 commits, 51 PRs): output byte-identical to the pre-refactor run. This is a pure refactor and the diff of the JSON proves it.
  • release-qa-status renders its markdown report unchanged.
  • 73 tests pass across the three packages.
  • Clean npm ci from the workspace root, then both scripts run exactly as the workflows invoke them.

Follow-up worth doing separately

Nothing in CI runs npm test for these scripts. The tests only ever run locally. A PR-triggered job over .github/scripts/** is what would actually catch this class of regression — happy to file it if you want it.

🤖 Generated with Claude Code

…ripts

release-qa-status was forked from gather-release-data and still carried a
verbatim copy of its GitHub transport: onThrottle, createOctokit,
parseRepo, listStandardReleaseTags, findPreviousTag, fetchCommitRange,
resolvePRNumbers and the CommitInfo/ReleaseRef types. ~184 lines,
differing only in comments, brace style and one error message.

Every maintenance change to that layer since the fork has had to patch
both copies — #37140 (for #37138) and #37213 (for #37201), both of them
bug fixes for defects that shipped twice. release-qa-status even carried
a findPreviousTag test whose stated purpose was "guards against drift
from gather-release-data"; the shared module makes that drift
structurally impossible, so the test is gone rather than duplicated.

What moved is plumbing only. fetchPRDetails stays in both callers: the
QA report needs url/author/authorType/externalRefs, the changelog needs
a truncated body and no author, and merging them means a union return
type with each caller ignoring half of it.

Mechanics:
- npm workspaces at .github/scripts — one install, one lockfile instead
  of two, and @octokit/* resolves from the shared module.
- Consumers import ../../shared/github by relative path, so there is no
  build-ordering step between packages.
- gather-release-data now runs through ts-node like release-qa-status
  already did. That drops a build step from the release-notes workflow
  and removes the rootDir constraint that blocks importing ../shared;
  tsc stays as a --noEmit type-check gate.

Verified: gather-release-data output over v26.08.24-01...v26.09.02-01 is
byte-identical to the pre-refactor run, release-qa-status renders its
markdown report, 73 tests pass across the three packages.

Closes: #37382

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claude

claude Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @sfreudenthaler's task in 3m 39s —— View job


Code Review

Reviewed the transport extraction, the workspace/build wiring, and both workflow call sites against f3dadc37^. The cut (transport → shared/, PR-shape logic left in each caller) is clean, the moved code is verbatim, and test coverage for the moved functions is preserved in shared/github.test.ts while extractLinkedIssues stays tested locally. One drift issue worth fixing.

New Issues

  • 🟡 Medium: .github/scripts/package-lock.json:20 — The lockfile's gather-release-data entry still declares "bin": { "gather-release-data": "dist/index.js" }, but gather-release-data/package.json removed the bin field in this PR (and dist/ is no longer built — the script runs via ts-node). The lockfile was not regenerated after that edit, so package.json and package-lock.json have drifted.
    • Assumption: npm ci validates dependency edges, not bin metadata, so it most likely still passes — leaving only a dangling node_modules/.bin/gather-release-data → dist/index.js symlink that nothing invokes. On that assumption this is non-blocking.
    • What to verify: run npm ci from .github/scripts on the branch. If it errors with the "package.json and package-lock.json are not in sync" (EUSAGE) message, this escalates to 🔴 — the Install script dependencies step in cicd_comp_ai-release-notes-phase.yml:86 has no continue-on-error, so a rejection there fails the entire release-notes phase (which the prior commit 21ede5c1 now alerts on). The QA-status install at cicd_6-release.yml:606 is continue-on-error, so that path degrades quietly instead.
    • Fix: cd .github/scripts && rm -rf node_modules && npm install, then commit the regenerated package-lock.json. That drops the stale bin and confirms the workspace resolves cleanly. (Fix this →)

Notes (non-blocking, not flagged as issues)

  • release-qa-status/package.json still carries "main"/"bin": "dist/index.js" and "build": "tsc" (emitting), while the workflow only ever runs it through ts-node. Harmless dead config, but the same dist/ cleanup you applied to gather-release-data would leave the two packages symmetric — the lockfile keeps a bin for it too.
  • tsconfig.json sets "noEmit": true and package.json sets "build": "tsc --noEmit" — redundant but intentional as a type-check gate; ts-node ignores noEmit at runtime, so nothing breaks.

Everything else checks out: relative-path import of ../../shared/github is unaffected by the workspace layout, @octokit/* resolves from the hoisted root node_modules, and the removed CommitInfo types are now sourced from shared/github.ts with no dangling references.

· refactor-share-release-github

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : CI/CD PR changes GitHub Actions/workflows

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

tech-debt: gather-release-data and release-qa-status duplicate 184 lines of GitHub transport, and it keeps causing paired bugs

1 participant