diff --git a/api/test/changelog.test.js b/api/test/changelog.test.js index a640f9ac..2612d758 100644 --- a/api/test/changelog.test.js +++ b/api/test/changelog.test.js @@ -173,3 +173,13 @@ test('release notes are the section body without the link definitions', () => { assert.equal(notesFor(sample, 'v1.1.0'), notes); assert.equal(notesFor(sample, '9.9.9'), null); }); + +/* A beta is tagged before its section is dated, so it has none of its own. With + no fallback the release page step fails after the image has published. */ +test('a prerelease falls back to its base version, then to Unreleased', () => { + assert.match(notesFor(sample, 'v1.2.0-beta.1'), /Widget for the doorbell\./); + assert.equal(notesFor(sample, 'v1.1.0-beta.1'), notesFor(sample, '1.1.0')); + + const nothingPending = sample.replace('### Added\n\n- Widget for the doorbell.\n\n', ''); + assert.equal(notesFor(nothingPending, 'v1.2.0-beta.1'), null); +}); diff --git a/scripts/release-notes.js b/scripts/release-notes.js index e3e792b4..d7961680 100644 --- a/scripts/release-notes.js +++ b/scripts/release-notes.js @@ -11,10 +11,30 @@ const cl = require('./changelog.js'); const ROOT = path.join(__dirname, '..'); +/** The section a tag describes. + + A prerelease has no section of its own: the changelog is dated when the + stable version is cut. `v1.8.0-beta.1` reads the 1.8.0 section if it already + exists, and [Unreleased] otherwise, which is what it is a candidate for. + + @param {string} markdown @param {string} version */ +function sectionFor(doc, version) { + const name = version.replace(/^v/, ''); + const exact = doc.versions.find(v => v.name === name); + if (exact) return exact; + const parsed = cl.parseTagName(name); + if (!parsed || !parsed.prerelease) return null; + const base = `${parsed.major}.${parsed.minor}.${parsed.patch}`; + const stable = doc.versions.find(v => v.name === base); + if (stable) return stable; + const unreleased = cl.unreleased(doc); + return unreleased && unreleased.sections.length ? unreleased : null; +} + /** @param {string} markdown @param {string} version */ function notesFor(markdown, version) { const doc = cl.parse(markdown); - const wanted = doc.versions.find(v => v.name === version.replace(/^v/, '')); + const wanted = sectionFor(doc, version); if (!wanted) return null; const next = doc.versions[doc.versions.indexOf(wanted) + 1]; const end = next ? next.line - 1 : doc.lines.length;