Skip to content

ci: harden and document the release procedure#268

Open
Kyleasmth wants to merge 19 commits into
mainfrom
ks/YPE-2486-release-hardening
Open

ci: harden and document the release procedure#268
Kyleasmth wants to merge 19 commits into
mainfrom
ks/YPE-2486-release-hardening

Conversation

@Kyleasmth

@Kyleasmth Kyleasmth commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Ports the release-hardening work from YPE-2486 to the React SDK.

What's here

  • RELEASE-RUNBOOK.md — 10 npm/Changesets failure modes with state-check + recovery commands.
  • docs/release-hardening-plan.md — engineering plan; records the keep-Changesets decision and per-AC status.
  • Commit-lint (AC6) — CI workflow anchored at the origin/main tip, husky commit-msg hook, and config (allows the YPE-#### prefix, ignores the release commit). Ported from the Kotlin SDK.
  • PUBLISHING.md — cross-links the runbook.

Greptile Summary

This PR hardens the release process by adding CI gates, corepack-aware git hooks, and comprehensive operator documentation. The changes are primarily CI/tooling with no package source modifications.

  • CI guardrails: Three new workflows enforce a changeset-per-PR requirement (changeset.yml), conventional PR title format (pr-title.yml), and per-commit lint via a merge-base-anchored range (commitlint.yml), using Node 24 and commitlint @19.8.1 to satisfy the >=22.13 engine floor.
  • Git hooks: .husky/pre-commit and the new .husky/commit-msg now prefer corepack pnpm ... with a plain pnpm fallback, per the documented Decision 2 rationale in docs/release-hardening-decisions.md.
  • Documentation: RELEASE-RUNBOOK.md catalogues 10 failure modes with state-check and recovery commands; docs/release-hardening-plan.md and docs/release-hardening-decisions.md record the engineering decisions and keep-Changesets rationale.

Confidence Score: 5/5

Safe to merge — all changes are CI workflows, git hooks, and documentation with no package source modifications.

No package code is touched. The three new GitHub Actions workflows are logically correct: the changeset gate uses a proper merge-base diff and excludes the release branch; the commitlint range is anchored to the live origin/main tip; the PR-title workflow is straightforward. The husky hooks follow the documented corepack-preferred / pnpm-fallback pattern. The commitlint dependency was pinned to @19.8.1 to satisfy the >=22.13 engine floor. The only findings are documentation nits — a missing permissions block in commitlint.yml and a stale status in the Decision 4 section of the decisions doc.

docs/release-hardening-decisions.md — the Decision 4 section body still reads as unresolved despite this PR shipping the gate.

Important Files Changed

Filename Overview
.github/workflows/commitlint.yml New workflow lints PR commits on Node 24 using a merge-base anchor against live origin/main; missing an explicit permissions: block unlike the other two new workflows.
.github/workflows/changeset.yml New workflow gates PRs on having at least one .changeset/*.md (excluding README); correctly exempts the changeset-release/main branch and uses merge-base diffing.
.github/workflows/pr-title.yml New workflow enforces Conventional Commits format on PR titles using amannn/action-semantic-pull-request; permissions correctly scoped to pull-requests:read.
commitlint.config.js Plain @commitlint/config-conventional config with anchored release-commit ignore regex and merge-commit exclusion; no YPE prefix parser per Decision 1.
.husky/commit-msg New hook follows the corepack-preferred / pnpm-fallback pattern required by Decision 2.
.husky/pre-commit Updated to corepack-preferred / pnpm-fallback shape for lint-staged, consistent with new commit-msg hook.
package.json Adds @commitlint/cli@19.8.1 and @commitlint/config-conventional@19.8.1; v19 satisfies the engines.node >=22.13 floor.
RELEASE-RUNBOOK.md New runbook with 10 failure-mode sections; uses per-package tags (@pkg@version) throughout, consistent with how Changesets creates tags.
docs/release-hardening-decisions.md New decisions document; header correctly marks all four decisions settled, but Decision 4's body section still shows stale 'unresolved' status.
docs/release-hardening-plan.md New engineering plan documenting the keep-Changesets decision and per-AC status; records the BREAKING CHANGE approval gate and dropped-scope items.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    PR[Pull Request opened / updated] --> PT[pr-title.yml\namannn/action-semantic-pull-request\nConventional Commits check on title]
    PR --> CL[commitlint.yml\nNode 24 · pnpm install\ngit merge-base origin/main HEAD\ncommitlint --from base --to head]
    PR --> CS[changeset.yml\nfetch-depth 0\ngit merge-base origin/main HEAD\ndiff .changeset *.md vs base]

    PT -->|title valid| PT_OK[✅ PR title gate passes]
    PT -->|invalid| PT_FAIL[❌ Block merge]

    CL -->|all commits pass| CL_OK[✅ Commitlint gate passes]
    CL -->|violation found| CL_FAIL[❌ Block merge]

    CS -->|changeset added| CS_OK[✅ Changeset gate passes]
    CS -->|no changeset| CS_FAIL[❌ Block merge\nRun pnpm changeset or\npnpm changeset --empty]

    PT_OK & CL_OK & CS_OK --> MERGE[Merge to main]
    MERGE --> REL[release.yml\nchangesets/action\nVersion Packages PR or publish]
Loading

Reviews (13): Last reviewed commit: "Merge branch 'main' into ks/YPE-2486-rel..." | Re-trigger Greptile

Context used (4)

  • Rule used - Git hooks should invoke the package manager via `c... (source)
  • Rule used - Conventional PR titles: the PR title must follow C... (source)
  • Rule used - Every PR must include a changeset. For a genuine n... (source)
  • Rule used - New devDependencies must support the consumer engi... (source)

@changeset-bot

changeset-bot Bot commented Jun 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6e53362

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread .github/workflows/commitlint.yml
Comment thread package.json Outdated
Comment thread RELEASE-RUNBOOK.md Outdated
Comment thread commitlint.config.js Outdated
Comment thread .husky/commit-msg Outdated
Comment thread commitlint.config.js Outdated
@jhampton

Copy link
Copy Markdown
Collaborator

⚠️ No Changeset found

Latest commit: 9e3c408

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets
When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

I understand that there are no changesets, but there should be one, or at least there should be a recommendation about the version impact. In a perfect world, we would at least see the next version calculated based on conventional commits and semantic release conventions. So in this case, there are two commits that contain the prefix fix. And for those, that should trigger a patch increase.

Now obviously when the PR lands, it would be a single patch level increase, not multiple patch level increases. I also wonder what happens if we don't have a change set and instead we decide to roll together n number of changes in a specific build. In that case, I suppose the next time we went to go do a change set, it would calculate and find the highest version bump that was available.

The problem with that is that now we have a batching problem. In lean software engineering, you'd want to be releasing more often. So the fact that there is a PR without a changeset to me feels like a smell or as possibly an anti pattern.

I'm willing to have the conversation and there are no right answers here. There are just a bunch of potentially wrong ones. So please take this as more of a, let's think about this – this is feedback v "sosmething here is wrong." I think this is suboptimal right now, and I think that we can probably improve it.

Those of us who are handling releases have the confidence that we're doing the right thing for each individual PR and that we're shipping improvements to the community as fast as humanly possible and as responsibly as our mission demands. For things like patch releases that may address small issues (and don't necessarily rise to the level of a point increase), most consumers will allow patch level increases for things like security fixes, or small bugs. But even we shouldn't wholesale be adopting point level increases, especially when we consider things like supply chain attacks.

Small PRs that are patch fixes and bug fixes tend to get approved as long as the change set is relatively small. The size of a change and its "reviewability" are a signal about a given change's impact, and smaller changes should receive careful-enough scrutiny to avoid loosening security or introducing other subtle bugs, especially since so many of us allow these patch-level increases automatically (like Dependabot, e.g.)

Things like point increases should trigger much more diligence. Our downstream dependencies and their transitive dependencies may have wider wider version ranges that they accept. But generally speaking, in this day and age, we should be pinning specific versions and maybe allowing for patch increases. And we should probably be telling our consumers and partners to do the same.

@jhampton jhampton left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take the feedback and make sure it's captured in this repo as learning (agents, skills, etc). Some of these need @davidfedor consulted if not deciding. We can (and should) defer landing this until we have clear decisions, then pin those behaviors with both deterministic (code/config) guardrails and semi-deterministic (Greptile, AGENTS.md) rules.

Comment thread .github/workflows/commitlint.yml
Comment thread .husky/commit-msg Outdated
Comment thread commitlint.config.js Outdated
Comment thread docs/release-hardening-decisions.md

@jhampton jhampton left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved the two questions. Lookin' good.

Comment thread docs/release-hardening-decisions.md Outdated
Comment thread docs/release-hardening-decisions.md Outdated
Comment thread docs/release-hardening-decisions.md Outdated
Comment thread docs/release-hardening-decisions.md Outdated
Comment thread docs/release-hardening-decisions.md Outdated
@Kyleasmth Kyleasmth changed the title YPE-2486: harden and document the release procedure ci: harden and document the release procedure (YPE-2486) Jul 20, 2026
@Kyleasmth Kyleasmth changed the title ci: harden and document the release procedure (YPE-2486) ci: harden and document the release procedure Jul 20, 2026
@Kyleasmth
Kyleasmth force-pushed the ks/YPE-2486-release-hardening branch from 578c2b4 to 7f7ece4 Compare July 20, 2026 21:34
@Kyleasmth
Kyleasmth requested a review from jhampton July 21, 2026 15:55
@Kyleasmth
Kyleasmth requested a review from davidfedor July 21, 2026 15:55
@jhampton
jhampton dismissed their stale review July 21, 2026 18:36

All feedback has been addressed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants