Skip to content

🐛 Drop ReleaseNotes singleton to fix multi-pass state leak (#111)#112

Open
glandais-nickel wants to merge 2 commits into
momocow:mainfrom
glandais-nickel:fix/release-notes-singleton-state-leak
Open

🐛 Drop ReleaseNotes singleton to fix multi-pass state leak (#111)#112
glandais-nickel wants to merge 2 commits into
momocow:mainfrom
glandais-nickel:fix/release-notes-singleton-state-leak

Conversation

@glandais-nickel
Copy link
Copy Markdown

Closes #111.

Problem

ReleaseNotes.get returned a process-wide singleton, so when
semantic-release ran analyzeCommits / generateNotes twice within a
single run (e.g. the channel-add pass that precedes a maintenance
release evaluation), two pieces of state leaked from pass 1 into pass 2:

  • _rtype, memoized on the instance, short-circuited pass 2's
    getReleaseType.
  • _context.commits, parsed once in the constructor, was never
    refreshed (updateContext does not touch it), so generateNotes
    rendered pass 1's commits in pass 2's notes.

Net effect on a maintenance branch with no release-worthy commit:
an unwanted release was emitted whose notes contained commits from
prior releases.

Fix

Construct a fresh ReleaseNotes per call from each entry point
(analyze-commits.js, generate-notes.js) and drop the static
get / _instance. semantic-release's per-call context.commits is
now always reflected. updateContext() is still invoked once on the
per-pass instance, so note rendering is unchanged.

This is option 2 from the issue's "Suggested fix" section — the
smaller change of the two.

Tests

  • New test/integration/release-notes-singleton.test.js covers both
    regression scenarios (release-type inheritance and commit-list
    pollution across passes).
  • The sinon stubs that previously bypassed the singleton in
    analyze-commits.test.js / generate-notes.test.js are removed
    (no longer needed, and broken without the static get).
  • npm test: 21 passing.

Demonstrate that the process-wide ReleaseNotes singleton retains
`_rtype` and `_context.commits` across analyzeCommits / generateNotes
calls, causing pass 2 (e.g. maintenance branch creation) to inherit
pass 1 state.

Marked `.failing` so the suite stays green until the singleton is fixed.
semantic-release reuses the same plugin process across analyzeCommits /
generateNotes invocations. The static `ReleaseNotes.get` returned a
shared instance whose `_rtype` cache and constructor-frozen
`_context.commits` polluted subsequent passes (e.g. the channel-add
pass run before a maintenance release evaluation).

Construct a fresh `ReleaseNotes` per call from each entry point so the
context (notably `context.commits`) provided by semantic-release is
always reflected. The existing test stubs that bypassed the singleton
are no longer needed.
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.

ReleaseNotes instance state leaks between semantic-release passes when adding a channel to an existing tag (maintenance branch creation)

1 participant