diff --git a/lib/deprecations.js b/lib/deprecations.js new file mode 100644 index 00000000..ae9a3119 --- /dev/null +++ b/lib/deprecations.js @@ -0,0 +1,56 @@ +'use strict'; + +const { promises: fs } = require('fs'); +const path = require('path'); +const replace = require('replace-in-file'); + +const newDeprecationPattern = +/<\s*a id="DEP0([X]+[0-9]*)+"[^>]*><\s*\/\s*a>/g; + +async function getUnmarkedDeprecations() { + const deprecationFilePath = path.resolve('doc', 'api', 'deprecations.md'); + const deprecationFile = await fs.readFile(deprecationFilePath, 'utf8'); + + const unmarkedDeprecations = [ + ...deprecationFile.matchAll(newDeprecationPattern) + ].map(m => m[1]); + + return unmarkedDeprecations; +} + +async function updateDeprecations(unmarkedDeprecations) { + const deprecationPattern = + /<\s*a id="DEP0([0-9]{3})+"[^>]*><\s*\/\s*a>/g; + + const deprecationFilePath = path.resolve('doc', 'api', 'deprecations.md'); + const deprecationFile = await fs.readFile(deprecationFilePath, 'utf8'); + + const deprecationNumbers = [ + ...deprecationFile.matchAll(deprecationPattern) + ].map(m => m[1]).reverse(); + + // Pull highest deprecation number off the list and increment from there. + let depNumber = parseInt(deprecationNumbers[0]) + 1; + + // Loop through each new unmarked deprecation number and replace instances. + for (const unmarked of unmarkedDeprecations) { + await replace({ + files: [ + 'doc/api/*.md', + 'lib/**/*.js', + 'src/**/*.{h,cc}', + 'test/**/*.js' + ], + ignore: 'test/common/README.md', + from: new RegExp(`DEP0${unmarked}`, 'g'), + to: `DEP0${depNumber}` + }); + + depNumber++; + } +} + +module.exports = { + updateDeprecations, + getUnmarkedDeprecations +}; diff --git a/lib/landing_session.js b/lib/landing_session.js index fc45c5ec..718b5c3a 100644 --- a/lib/landing_session.js +++ b/lib/landing_session.js @@ -1,14 +1,16 @@ 'use strict'; const path = require('path'); +const { + getUnmarkedDeprecations, + updateDeprecations +} = require('./deprecations'); const { runAsync, runSync, forceRunAsync } = require('./run'); const Session = require('./session'); -const { - shortSha -} = require('./utils'); +const { shortSha } = require('./utils'); const isWindows = process.platform === 'win32'; @@ -84,6 +86,21 @@ class LandingSession extends Session { process.exit(1); } } + + // Check for and maybe assign any unmarked deprecations in the codebase. + const unmarkedDeprecations = await getUnmarkedDeprecations(); + const unmarkedDepCount = unmarkedDeprecations.length; + if (unmarkedDepCount > 0) { + cli.startSpinner('Assigning deprecation numbers to DEPOXXX items'); + + // Update items then stage files and amend the last commit. + await updateDeprecations(unmarkedDeprecations); + await runAsync('git', ['add', 'doc', 'lib', 'src', 'test']); + await runAsync('git', ['commit', '--amend', '--no-edit']); + + cli.stopSpinner(`Updated ${unmarkedDepCount} DEPOXXX items in codebase`); + } + cli.ok('Patches applied'); return patch; } diff --git a/lib/prepare_release.js b/lib/prepare_release.js index 9a5b12c9..e664d81d 100644 --- a/lib/prepare_release.js +++ b/lib/prepare_release.js @@ -1,13 +1,17 @@ 'use strict'; const path = require('path'); -const fs = require('fs').promises; +const { promises: fs } = require('fs'); const semver = require('semver'); const replace = require('replace-in-file'); const { getMergedConfig } = require('./config'); const { runAsync, runSync } = require('./run'); const { writeJson, readJson } = require('./file'); +const { + getUnmarkedDeprecations, + updateDeprecations +} = require('./deprecations'); const isWindows = process.platform === 'win32'; @@ -113,6 +117,26 @@ class ReleasePreparation { await this.updateREPLACEMEs(); cli.stopSpinner('Updated REPLACEME items in docs'); + // Check for and maybe assign any unmarked deprecations in the codebase. + const unmarkedDeprecations = await getUnmarkedDeprecations(); + const unmarkedDepCount = unmarkedDeprecations.length; + if (unmarkedDepCount > 0) { + if (unmarkedDepCount === 1) { + cli.startSpinner( + 'Assigning deprecation number to DEPOXXX item'); + await updateDeprecations(unmarkedDeprecations); + cli.stopSpinner('Assigned deprecation numbers to DEPOXXX items'); + } else { + cli.warn( + 'More than one unmarked DEPOXXX item - manual resolution required.'); + + await cli.prompt( + `Finished updating ${unmarkedDepCount} unmarked DEPOXXX items?`, + { defaultAnswer: false }); + cli.stopSpinner(`Finished updating ${unmarkedDepCount} DEPOXXX items`); + } + } + // Fetch date to use in release commit & changelogs. const todayDate = new Date().toISOString().split('T')[0]; this.date = await cli.prompt('Enter release date in YYYY-MM-DD format:',