Object.defineProperty(exports, '__esModule', { value: true }); var fs = require('node:fs'); var node_os = require('node:os'); var bumpp = require('bumpp'); var changelogithub = require('changelogithub'); var conventionalRecommendedBump = require('conventional-recommended-bump'); var kolorist = require('kolorist'); var releaseIt = require('release-it'); var semver = require('semver'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var fs__default = /*#__PURE__*/_interopDefault(fs); var semver__default = /*#__PURE__*/_interopDefault(semver); function fixChangelogTag(content) { if (typeof content !== 'string') { return content; } const tag = content.match(/^## (\S+)$/m).at(1); if (!tag) { return content; } const replaceRegex = /(\[View changes on GitHub\]\(\S+\.\.\.)main\)$/m; return content.replace(replaceRegex, `$1${tag})`); } const prompts = { publish: { type: 'confirm', message: ()=>'Are you sure you want to publish package?' }, release: { type: 'confirm', message: ()=>'Are you sure you want to create a new release on GitHub?' } }; const defaultPublishCommand = 'pnpm -r publish --access public --no-git-checks --tag $tag'; class ReleaseItPnpmPlugin extends releaseIt.Plugin { static disablePlugin() { return [ 'npm', 'version' ]; } constructor(...args){ super(...args); this.registerPrompts(prompts); } getInitialOptions(options, pluginName) { return Object.assign({}, options[pluginName], { 'dry-run': options['dry-run'], 'ci': options.ci, 'preRelease': options.preRelease, 'verbose': options.verbose }); } getIncrement(options) { return options.increment; } getIncrementedVersionCI(options) { return this.getRecommendedVersion(options); } getIncrementedVersion(options) { return this.getRecommendedVersion(options); } async getRecommendedVersion({ latestVersion, increment, isPreRelease, preReleaseId }) { this.debug('release-it-pnpm:getRecommendedVersion', { increment, latestVersion, isPreRelease, preReleaseId }); const { options } = this; this.debug('release-it-pnpm:getRecommendedVersion', { options }); if (!options.ci) { const result = await bumpp.versionBump({ commit: false, tag: false, push: false, confirm: true, preid: preReleaseId, files: [ 'this-is-a-non-existing-file-i-believe-you-do-not-have-it.txt' ] }); return semver__default.default.valid(result.newVersion); } try { const bumper = new conventionalRecommendedBump.Bumper(process.cwd()).loadPreset({ name: 'conventionalcommits', preMajor: semver__default.default.lt(latestVersion, '1.0.0') }); const result = await bumper.bump(); this.debug('release-it-pnpm:getRecommendedVersion', { result }); let { releaseType } = result; if (increment) { this.log.warn(`The recommended bump is "${releaseType}", but is overridden with "${increment}".`); releaseType = increment; } if (increment && semver__default.default.valid(increment)) { return increment; } else if (isPreRelease) { const type = releaseType && !semver__default.default.prerelease(latestVersion) ? `pre${releaseType}` : 'prerelease'; return semver__default.default.inc(latestVersion, type, preReleaseId); } else if (!releaseType) { return null; } return semver__default.default.inc(latestVersion, releaseType, preReleaseId); } catch (err) { this.debug('release-it-pnpm:getRecommendedVersion', { err }); throw err; } } async bump(newVersion) { this.setContext({ newVersion }); const { publishCommand = defaultPublishCommand } = this.options; const { inFile } = this.options; const isDryRun = this.options['dry-run']; let needPublish = false; if (!this.options['dry-run']) { const { updatedFiles } = await bumpp.versionBump({ commit: false, tag: false, push: false, confirm: false, recursive: true, release: newVersion }); if (updatedFiles.length === 0) return; // Only publish when some packages is not private for (const file of updatedFiles){ const { private: isPrivate } = JSON.parse(fs__default.default.readFileSync(file, 'utf8')); if (!isPrivate) { needPublish = true; break; } } // Using custom publish command if (publishCommand !== defaultPublishCommand) needPublish = true; } const { prerelease } = semver__default.default.parse(newVersion); const includePrerelease = prerelease.length > 0; const tag = prerelease[0] ?? 'latest'; this.debug('release-it-pnpm:bump', { needPublish, publishCommand, includePrerelease, prerelease, tag, newVersion, parsedNewVersion: semver__default.default.parse(newVersion) }); this.log.exec(`Writing changelog to ${inFile}`, isDryRun); if (inFile && !isDryRun) { const { md } = await changelogithub.generate(); await this.writeChangelog(md, newVersion); } if (needPublish) { await this.step({ task: ()=>this.exec(publishCommand.replace('$tag', tag)), label: 'Publishing packages(s)', prompt: 'publish' }); } } async writeChangelog(changelog, version) { const { inFile, header: _header = '# Changelog' } = this.options; const header = _header.split(/\r\n|\r|\n/g).join(node_os.EOL); let hasInFile = false; try { fs__default.default.accessSync(inFile); hasInFile = true; } catch (err) { this.debug(err); } let previousChangelog = ''; try { previousChangelog = await fs__default.default.promises.readFile(inFile, 'utf8'); previousChangelog = previousChangelog.replace(header, ''); } catch (err) { this.debug(err); } const currentChangelog = fixChangelogTag(`## ${version}${changelog ? node_os.EOL + node_os.EOL + changelog.trim() : ''}`); fs__default.default.writeFileSync(inFile, `${header + node_os.EOL + node_os.EOL}${currentChangelog}${previousChangelog ? node_os.EOL + node_os.EOL + previousChangelog.trim() : ''}${node_os.EOL}`); if (!hasInFile) await this.exec(`git add ${inFile}`); } async release() { if (this.options?.disableRelease) return; await this.step({ task: async ()=>{ let token = process.env.GITHUB_TOKEN; if (!token) { try { token = await this.exec('gh auth token'); } catch (e) { this.debug('release-it-pnpm:release', e); } } let webUrl = ''; try { const { config, md, commits } = await changelogithub.generate({ token, emoji: true, dry: this.options['dry-run'] }); webUrl = `https://${config.baseUrl}/${config.repo}/releases/new?title=${encodeURIComponent(String(config.name || config.to))}&body=${encodeURIComponent(String(md))}&tag=${encodeURIComponent(String(config.to))}&prerelease=${config.prerelease}`; this.debug('release-it-pnpm:release', { config, md, commits }); if (this.options['verbose']) { this.log.log(kolorist.cyan(config.from) + kolorist.dim(' -> ') + kolorist.blue(config.to) + kolorist.dim(` (${commits.length} commits)`)); this.log.log(kolorist.dim('--------------')); this.log.log(); this.log.log(md.replaceAll(' ', '')); this.log.log(); this.log.log(kolorist.dim('--------------')); } const printWebUrl = ()=>{ this.log.log(); this.log.error(kolorist.yellow('Using the following link to create it manually:')); this.log.error(kolorist.yellow(webUrl)); this.log.log(); }; if (config.dry) { this.log.log(kolorist.yellow('Dry run. Release skipped.')); printWebUrl(); return; } if (!config.token) { this.log.error(kolorist.red('No GitHub token found, specify it via GITHUB_TOKEN env. Release skipped.')); printWebUrl(); return; } if (!await changelogithub.hasTagOnGitHub(config.to, config)) { this.log.error(kolorist.yellow(`Current ref "${kolorist.bold(config.to)}" is not available as tags on GitHub. Release skipped.`)); process.exitCode = 1; printWebUrl(); return; } if (commits.length === 0 && await changelogithub.isRepoShallow()) { this.log.error(kolorist.yellow('The repo seems to be clone shallowly, which make changelog failed to generate. You might want to specify `fetch-depth: 0` in your CI config.')); process.exitCode = 1; printWebUrl(); return; } await changelogithub.sendRelease(config, md); } catch (e) { this.log.error(kolorist.red(String(e))); if (e?.stack) this.log.error(kolorist.dim(e.stack?.split('\n').slice(1).join('\n'))); if (webUrl) { this.log.log(); this.log.error(kolorist.red('Failed to create the release. Using the following link to create it manually:')); this.log.error(kolorist.yellow(webUrl)); this.log.log(); } // eslint-disable-next-line unicorn/no-process-exit process.exit(1); } }, label: 'Creating release on GitHub', prompt: 'release' }); } } exports.default = ReleaseItPnpmPlugin;