Skip to content

Release Incidents

martyy-code edited this page Aug 5, 2026 · 1 revision

Last synced from docs/engineering/process/release-incidents.md on 2026-08-05. The repo file is the source of truth. If the two diverge, follow the repo.

This page is the runbook for handling a release incident: a published version of @deessejs/fp that turns out to be broken, insecure, or otherwise unfit for production. It assumes the reader is a maintainer with npm publish rights and GitHub write access.

Outline

  1. What is a release incident
  2. The three actions
  3. Decision tree: which action to take
  4. Procedure: deprecate
  5. Procedure: revert
  6. Procedure: hotfix
  7. Communication
  8. Related documents

1. What is a release incident

A release incident is any situation where a published version of @deessejs/fp causes harm to a consumer. Typical cases:

  • Bug regression — a feature that worked in version N breaks in version N+1.
  • Type breakage — a type signature changed and downstream consumers can no longer compile.
  • Security vulnerability — a CVE is found in the published code.
  • Performance regression — a benchmark drops by a meaningful margin.
  • Dependency drift — a transitive dependency was updated and breaks consumers.

The trigger is not always a bug in @deessejs/fp — it can be a change in the ecosystem (Node.js deprecation, npm registry policy change, peer dependency update from another package). The shared property is that consumers are affected and need to either be informed or get a fix.

2. The three actions

When a release incident happens, the maintainer has three options:

  • Deprecate — mark the bad version with npm deprecate, telling consumers not to install it. The version stays on the registry, installable, but with a warning at install time.
  • Revert — submit a git revert commit on main that undoes the bad commit. The next regular release (or a back-merge) carries the revert. No new version is published by the revert itself.
  • Hotfix — write a fix on a hotfix/* branch, merge it directly to main, and publish a new patch version. See the Hotfix Flow page for the full process.

These three actions are not mutually exclusive. A typical sequence:

  1. Deprecate the bad version immediately (cost: 30 seconds).
  2. Investigate the root cause.
  3. Decide whether to revert or hotfix.
  4. Ship the fix (revert or hotfix).
  5. Communicate.

3. Decision tree: which action to take

Start at the top of the tree, take the first branch that matches.

Is the bad version actively dangerous (security, data loss)?
├── YES  → deprecate immediately. Continue investigation in parallel.
└── NO   ↓

Is the cause of the bug known and the fix is small (one commit)?
├── YES  → hotfix (write the fix, publish a new patch).
└── NO   ↓

Is the cause of the bug known and the fix is large?
├── YES  → revert. Cut a follow-up release with the revert.
└── NO   ↓

Is the cause of the bug unknown?
└── Revert the last release, then investigate without pressure.
   Do not ship a new version until the cause is known and fixed.

In all cases, deprecate the bad version as the first reflex, even if you plan to revert or hotfix afterwards. The deprecation is reversible; the bad version sitting on the registry is not.

4. Procedure: deprecate

npm deprecate is a one-line operation that marks a version with a warning. The version is not removed; it stays on the registry but consumers see a warning when they install it.

# Format: npm deprecate <package>@<version> "<message>"
npm deprecate @deessejs/fp@1.2.3 "Critical regression in Result.fold. Please upgrade to >=1.2.4."

The message is what consumers see in their install output. Write it for the end user, not for the maintainer:

  • Lead with what broke.
  • Say what to do (upgrade to X, or revert to Y).
  • Avoid internal jargon.

After deprecating, no commit is needed on main (the registry change is independent of the codebase). The next release's CHANGELOG should mention the deprecation in the affected version's entry.

Limits

  • Not retroactive: npm deprecate warns on install but does not uninstall the version. A consumer with a lockfile pinning the bad version is not warned.
  • Public: anyone sees the deprecation message, including competitors.
  • Permanent (sort of): there is no npm undeprecate to undo. The only way is to publish a new version with no deprecation, but the old one keeps its marker.

5. Procedure: revert

A revert is a git revert of the offending commit, merged to main. The next release carries the revert; the version is unchanged but the published code is back to a known-good state.

# 1. Identify the offending commit
git log --oneline main | head -20

# 2. Create a revert branch
git checkout -b revert/1.2.3 main

# 3. Revert the commit
git revert <commit-sha>

# 4. Add a Changeset describing the revert
echo '---
"@deessejs/fp": patch
---

Revert "feat: Result.fold on circular references" (#123).' \
  > .changeset/cyan-panda-revert.md

# 5. Commit the revert + Changeset
git add -A
git commit -m 'revert: Result.fold on circular references (#123)'

# 6. Push, open a PR, get review, merge to main
git push origin HEAD
gh pr create --base main

The merge triggers the normal Release Process: the next PR merge publishes a new patch version with the revert.

When to prefer revert over hotfix

  • The cause is a single commit (or a small, isolated set of commits).
  • The fix is "remove what was added", not "add a new thing".
  • The maintainer wants to keep the bad commit's history visible (with a revert marker) for forensic purposes.

When to avoid revert

  • The cause spans many commits and reverting would touch too many files.
  • The bug requires a new implementation, not a removal.

6. Procedure: hotfix

A hotfix writes a new commit that fixes the bug, merges to main, and publishes a patch version. See the Hotfix Flow page for the full procedure.

When to prefer hotfix over revert

  • The bug has a known root cause and a known fix.
  • The fix is small (one commit) but not a simple revert.
  • You want the bad version's CHANGELOG entry to say "fixed in N+1" rather than "reverted in N+1".

When to avoid hotfix

  • The cause is unknown (writing a hotfix without understanding the bug is gambling).
  • Multiple consumers are affected and need time to migrate to a workaround.

7. Communication

Communication is part of the response, not an afterthought. Channels, in order of priority:

  1. GitHub Security Advisory (for security incidents only): file a GitHub Security Advisory on the repo. This triggers CVE assignment and notifies GitHub's security database. Use npm deprecate with the CVE ID in the message so consumers running audit tools see it.
  2. GitHub Issue with the bug or security label: a public issue describing the problem, the affected versions, and the workaround. This is the canonical place for the conversation.
  3. CHANGELOG entry: the next regular release's CHANGELOG entry for the affected version should mention the incident in plain language ("Critical bug in Result.fold, fixed in 1.2.4").
  4. GitHub Release notes: if the affected release has a GitHub Release page, edit it to add a note at the top. Pin a comment if the page already has user comments.

Do not communicate via:

  • Commit messages alone — most consumers don't read them.
  • Direct messages to a few users — leaves others unaware.
  • Closing the issue without a comment — leaves consumers wondering if they are affected.

8. Related documents