UNPKG

@unconfig/changeset-config

Version:

🚀 The package offer changeset-config for @unconfig!

346 lines (313 loc) • 12.8 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/changelog-generate.ts var _fs = require('fs'); var _assemblereleaseplan = require('@changesets/assemble-release-plan'); var _assemblereleaseplan2 = _interopRequireDefault(_assemblereleaseplan); var _config = require('@changesets/config'); var _pre = require('@changesets/pre'); var _read = require('@changesets/read'); var _read2 = _interopRequireDefault(_read); var _getpackages = require('@manypkg/get-packages'); var _meta = require('@unconfig/meta'); function getReleaseSummary(changesets, release) { const formattedChangesets = release.changesets.map((changeset) => { const { summary = "" } = _nullishCoalesce(changesets.find((cs) => cs.id === changeset), () => ( {})); const changes = summary.split("\n"); return changes.map( (change) => !change || _optionalChain([change, 'optionalAccess', _ => _.trim, 'call', _2 => _2(), 'access', _3 => _3.startsWith, 'call', _4 => _4("-")]) ? change : `- ${change} ` ).join(""); }); const displayName = `**${release.name}** \`v${release.newVersion}\``; return { ...release, changesets: formattedChangesets, displayName: displayName.replace(/,\s*$/, "") }; } async function getChangesetEntries(options) { const { packages: changelogPackges, ignorePackages: ignoreChangelogPackages, cwd } = options; const packages = await _getpackages.getPackages.call(void 0, cwd); const preState = await _pre.readPreState.call(void 0, cwd); const config = await _config.read.call(void 0, cwd, packages); const changesets = await _read2.default.call(void 0, cwd); const releasePlan = _assemblereleaseplan2.default.call(void 0, changesets, packages, config, preState ); const releases = releasePlan.releases.filter((release) => release.changesets.length > 0).filter((release) => !ignoreChangelogPackages.includes(release.name)).map((release) => getReleaseSummary(releasePlan.changesets, release)).sort((a, b) => { if (changelogPackges.includes(a.name)) return -1; if (changelogPackges.includes(b.name)) return 1; return a.name < b.name ? -1 : 1; }); return releases; } async function changesetsChangelogGenerate(options) { const { packages, ignorePackages = [], cwd, projectChangelogTempPath = _meta.PROJECT_CHANGELOG_TEMP_FILE } = options; if (!cwd) return; const releases = await getChangesetEntries({ packages, ignorePackages, cwd }); if (!releases.length) return; const content = JSON.parse(_fs.readFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`).toString()) || {}; releases.forEach(({ displayName, changesets }) => { const prevState = content[displayName] || []; content[displayName] = [.../* @__PURE__ */ new Set([...prevState, ...changesets])]; }); _fs.writeFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`, JSON.stringify(content)); } // src/changelog-write.ts var _prettier = require('prettier'); var _prettier2 = _interopRequireDefault(_prettier); function getCurrentDate() { const date = /* @__PURE__ */ new Date(); const day = date.getDate().toString().padStart(2, "0"); const month = (date.getMonth() + 1).toString().padStart(2, "0"); const year = date.getFullYear(); return [ `## ${day}-${month}-${year}`, "\n\n", `### ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}` ].join(""); } async function getContent(releases, prettierConfig) { const releaseEntries = Object.entries(releases).map((release) => { const [displayName, changesets] = release; return [displayName, "\n\n", ...changesets].join(""); }); let content = [getCurrentDate(), ...releaseEntries].join("\n"); content = await _prettier2.default.format(content, prettierConfig); return content; } async function changesetsChangelogWrite(options) { const { projectChangelogPath = _meta.PROJECT_CHANGELOG_FILE, projectChangelogTempPath = _meta.PROJECT_CHANGELOG_TEMP_FILE, websiteChangelogPath = _meta.PROJECT_WEBSITE_CHANGELOG_FILE, cwd, prettierConfig = { parser: "markdown", singleQuote: true, trailingComma: "es5" } } = options; if (!cwd) return; const releases = JSON.parse( _fs.readFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`).toString() ); if (!Object.entries(releases).length) return; const content = await getContent(releases, prettierConfig); const changelog = _fs.readFileSync.call(void 0, `${cwd}/${projectChangelogPath}`, "utf8"); const newChangelog = changelog.replace( "<!-- CHANGELOG:INSERT -->", `<!-- CHANGELOG:INSERT --> ${content}` ); _fs.writeFileSync.call(void 0, `${cwd}/${projectChangelogPath}`, newChangelog); _fs.writeFileSync.call(void 0, `${cwd}/${websiteChangelogPath}`, newChangelog.replace("<!-- CHANGELOG:INSERT -->\n\n", "") ); _fs.writeFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`, "{}"); } // src/generate-releases.ts var _path = require('path'); var _child_process = require('child_process'); var _process = require('process'); var _process2 = _interopRequireDefault(_process); var _core = require('@octokit/core'); var _semver = require('semver'); var _semver2 = _interopRequireDefault(_semver); async function createRelease(octokit, { pkg, tagName, repoName, repoOwner, projectChangelogPath }) { const changelogPath = _path.resolve.call(void 0, pkg.dir, projectChangelogPath); const changelog = _fs.readFileSync.call(void 0, changelogPath, "utf8"); const changelogArr = changelog.split("\n"); const releaseNotes = []; for (const line of changelogArr) { if (/^#{3}\s/.test(line)) releaseNotes.push(line); else if (/^#{1,3}\s/.test(line) && releaseNotes.length > 0) break; else if (releaseNotes.length > 0) releaseNotes.push(line); } const prereleaseParts = _semver2.default.prerelease(tagName.replace(`${pkg.packageJson.name}@`, "")) || []; try { const params = { owner: repoOwner, repo: repoName, name: tagName, tag_name: tagName, body: releaseNotes.join("\n"), prerelease: prereleaseParts.length > 0 }; await octokit.request("POST /repos/{owner}/{repo}/releases", params); } catch (error) { console.warn( "[octokit 'POST /repos/{owner}/{repo}/releases'] has error.", error ); } } function getReleasedPackages(csOutput, pkgs, pkgPrefix) { const tagNameRegex = new RegExp( // eslint-disable-next-line no-useless-escape `(${pkgPrefix}/[^@]+)@([^s]+)` ); return csOutput.split("\n").reduce((acc, line) => { const newTagPkgContent = line.includes("New tag:") ? line.split("New tag:")[1].trim() : ""; if (!newTagPkgContent) return acc; const match = newTagPkgContent.match(tagNameRegex); if (match === null) return acc; const tagName = [match[1], match[2]].join("@"); const pkg = pkgs.find((p) => _optionalChain([p, 'access', _5 => _5.packageJson, 'optionalAccess', _6 => _6.name]) === match[1]); return [...acc, { tagName, pkg }]; }, []); } async function changesetsGenerateReleases(options) { const { repoName = _meta.REPO_NAME, repoOwner = _meta.REPO_OWNER, pkgPrefix = _meta.PKG_PREFIX, projectChangelogPath = _meta.PROJECT_CHANGELOG_FILE, cwd } = options; if (!cwd) return; const env = _process2.default.env; const octokit = new (0, _core.Octokit)({ auth: env.GITHUB_TOKEN }); const publishCommandOutput = _child_process.execSync.call(void 0, "pnpm changeset publish").toString(); console.log( ` \u{1F680}\u{1F680}\u{1F680} Run changesets publish and get stdout. \u{1F680}\u{1F680}\u{1F680} ${publishCommandOutput} ` ); const gitPushCommand = `git pull && git add . && git diff --staged --quiet || git commit -m "docs: \u{1F4DD} add changelogs for $(git rev-parse --short HEAD) [skip ci]" && git push origin ${env.GITHUB_BRANCH} --follow-tags`; const gitPushCommandOutput = _child_process.execSync.call(void 0, gitPushCommand).toString(); console.log( ` \u{1F680}\u{1F680}\u{1F680} Push updated packages to github with tags. \u{1F680}\u{1F680}\u{1F680} ${gitPushCommandOutput} ` ); const { packages: pkgs } = await _getpackages.getPackages.call(void 0, cwd); const releasedPkgs = getReleasedPackages( publishCommandOutput, pkgs, pkgPrefix ); for (const pkg of releasedPkgs) { await createRelease(octokit, { ...pkg, repoName, repoOwner, projectChangelogPath }); } console.log(`\u{1F680}\u{1F680}\u{1F680} Create release for each published package. \u{1F680}\u{1F680}\u{1F680}`); } // src/manual-generate-prereleases.ts var _inquirer = require('inquirer'); var _inquirer2 = _interopRequireDefault(_inquirer); function updatePackageJson(pkgJsonPath, version) { const pkgRaw = _fs.readFileSync.call(void 0, pkgJsonPath, { encoding: "utf-8" }); const stringified = pkgRaw.replace( /("version".*?) (".*?")/i, `$1 "${version}"` ); _fs.writeFileSync.call(void 0, pkgJsonPath, stringified); } async function ignorePackage(pkgName, cwd, projectChangesetsPath) { const changesetConfigPath = _path.resolve.call(void 0, cwd, projectChangesetsPath); const rawConfig = _fs.readFileSync.call(void 0, changesetConfigPath, { encoding: "utf-8" }); const jsonConfig = JSON.parse(rawConfig); const ignorePkgs = jsonConfig.ignore || []; if (!ignorePkgs.includes(pkgName)) { jsonConfig.ignore = [pkgName, ...ignorePkgs]; const stringified = JSON.stringify(jsonConfig, null, 2); await _fs.writeFileSync.call(void 0, changesetConfigPath, stringified, { encoding: "utf-8" }); } } async function manualGeneratePrereleases(options) { const { npmRegistryUrl = _meta.NPM_REGISTRY_URL, projectChangesetsPath = _meta.PROJECT_CHANGESETS_CONFIG_FILE, cwd } = options; if (!cwd) return; const { packages } = await _getpackages.getPackages.call(void 0, cwd); const choices = packages.map(({ packageJson: packageJson2 }) => ({ name: `${packageJson2.name} (${packageJson2.version})`, value: packageJson2.name })).concat(new _inquirer2.default.Separator()); const { pkgName } = await _inquirer2.default.prompt([ { pageSize: 12, name: "pkgName", message: "Which package to make a pre-release?", type: "list", choices } ]); const { packageJson, dir } = packages.find( ({ packageJson: packageJson2 }) => packageJson2.name === pkgName ); const { version, name } = packageJson; const prereleaseTag = _optionalChain([_semver2.default, 'access', _7 => _7.prerelease, 'call', _8 => _8(version), 'optionalAccess', _9 => _9[0]]); const { tag, publish } = await _inquirer2.default.prompt([ { name: "tag", message: "Which tag should be used for the pre-release?", type: "list", choices: [ { name: "alpha" }, { name: "beta" } ], default: prereleaseTag }, { name: "publish", message: "Should the package be published?", type: "confirm" } ]); const increase = prereleaseTag === tag ? "prerelease" : "preminor"; const newVersion = _semver2.default.inc(version, increase, tag); await updatePackageJson(_path.resolve.call(void 0, dir, "package.json"), newVersion); await ignorePackage(name, cwd, projectChangesetsPath); if (publish) { await _child_process.exec.call(void 0, `npm publish ${dir} --tag ${tag}`, (error, stdout, stderr) => { if (!error) { console.log(stdout); console.log( `${name}@${newVersion} published: ${npmRegistryUrl}/${name} ` ); } else { console.error(error); console.error(stderr); } }); } else { console.log(`Version for ${name} updated on package.json.`); } } exports.changesetsChangelogGenerate = changesetsChangelogGenerate; exports.changesetsChangelogWrite = changesetsChangelogWrite; exports.changesetsGenerateReleases = changesetsGenerateReleases; exports.manualGeneratePrereleases = manualGeneratePrereleases;