UNPKG

changesets-gitlab

Version:

[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/un-ts/changesets-gitlab/ci.yml?branch=main)](https://github.com/un-ts/changesets-gitlab/actions/workflows/ci.yml?query=branch%3Amain) [![CodeRabbit Pull Request Revie

202 lines (200 loc) 8.82 kB
import fs from 'node:fs/promises'; import path from 'node:path'; import { exec } from '@actions/exec'; import { getPackages } from '@manypkg/get-packages'; import pLimit from 'p-limit'; import resolveFrom from 'resolve-from'; import semver from 'semver'; import { createApi } from "./api.js"; import * as context from './context.js'; import * as gitUtils from './git-utils.js'; import readChangesetState from './read-changeset-state.js'; import { cjsRequire, execWithOutput, getChangedPackages, getChangelogEntry, getOptionalInput, getVersionsByDirectory, GITLAB_MAX_TAGS, sortTheThings, } from './utils.js'; const limit = pLimit(2 * 3); export const createRelease = async (api, { pkg, tagName }) => { try { const changelogFileName = path.join(pkg.dir, 'CHANGELOG.md'); const changelog = await fs.readFile(changelogFileName, 'utf8'); const changelogEntry = getChangelogEntry(changelog, pkg.packageJson.version); if (!changelogEntry) { throw new Error(`Could not find changelog entry for ${pkg.packageJson.name}@${pkg.packageJson.version}`); } await api.ProjectReleases.create(context.projectId, { name: tagName, tag_name: tagName, description: changelogEntry.content, pre_release: pkg.packageJson.version.includes('-'), }); } catch (err) { if (err.code !== 'ENOENT') { throw err; } } }; export async function runPublish({ script, gitlabToken, createGitlabReleases = true, cwd = process.cwd(), }) { const api = createApi(gitlabToken); const [publishCommand, ...publishArgs] = script.split(/\s+/); const changesetPublishOutput = await execWithOutput(publishCommand, publishArgs, { cwd }); const { packages, tool } = await getPackages(cwd); const pushAllTags = packages.length <= GITLAB_MAX_TAGS || (await api.FeatureFlags.show(context.projectId, 'git_push_create_all_pipelines') .then(({ active }) => active) .catch(() => false)); if (pushAllTags) { await gitUtils.pushTags(); } const releasedPackages = []; if (tool === 'root') { if (packages.length !== 1) { throw new Error(`No package found.` + 'This is probably a bug in the action, please open an issue'); } const pkg = packages[0]; const newTagRegex = /New tag:/; for (const line of changesetPublishOutput.stdout.split('\n')) { const match = newTagRegex.exec(line); if (match) { releasedPackages.push(pkg); const tagName = `v${pkg.packageJson.version}`; if (createGitlabReleases) { await createRelease(api, { pkg, tagName }); } break; } } } else { const newTagRegex = /New tag:\s+(@[^/]+\/[^@]+|[^/]+)@(\S+)/; const packagesByName = new Map(packages.map(x => [x.packageJson.name, x])); for (const line of changesetPublishOutput.stdout.split('\n')) { const match = newTagRegex.exec(line); if (match === null) { continue; } const pkgName = match[1]; const pkg = packagesByName.get(pkgName); if (pkg === undefined) { throw new Error(`Package "${pkgName}" not found.` + 'This is probably a bug in the action, please open an issue'); } releasedPackages.push(pkg); } if (!pushAllTags) { await Promise.all(releasedPackages.map(pkg => gitUtils.pushTag(`${pkg.packageJson.name}@${pkg.packageJson.version}`))); } if (createGitlabReleases) { await Promise.all(releasedPackages.map(pkg => limit(() => createRelease(api, { pkg, tagName: `${pkg.packageJson.name}@${pkg.packageJson.version}`, })))); } } if (releasedPackages.length > 0) { return { published: true, publishedPackages: releasedPackages.map(pkg => ({ name: pkg.packageJson.name, version: pkg.packageJson.version, })), }; } return { published: false }; } const requireChangesetsCliPkgJson = (cwd) => { try { return cjsRequire(resolveFrom(cwd, '@changesets/cli/package.json')); } catch (err) { if (err?.code === 'MODULE_NOT_FOUND') { throw new Error(`Have you forgotten to install \`@changesets/cli\` in "${cwd}"?`); } throw err; } }; export async function runVersion({ script, gitlabToken, cwd = process.cwd(), mrTitle = 'Version Packages', mrTargetBranch = context.ref, commitMessage = 'Version Packages', removeSourceBranch = false, hasPublishScript = false, }) { const currentBranch = context.ref; const versionBranch = `changeset-release/${currentBranch}`; const api = createApi(gitlabToken); const { preState } = await readChangesetState(cwd); await gitUtils.switchToMaybeExistingBranch(versionBranch); await exec('git', ['fetch', 'origin', currentBranch]); await gitUtils.reset(`origin/${currentBranch}`); const labels = getOptionalInput('labels') ?.split(',') .map(x => x.trim()); const versionsByDirectory = await getVersionsByDirectory(cwd); if (script) { const [versionCommand, ...versionArgs] = script.split(/\s+/); await exec(versionCommand, versionArgs, { cwd }); } else { const changesetsCliPkgJson = requireChangesetsCliPkgJson(cwd); const cmd = semver.lt(changesetsCliPkgJson.version, '2.0.0') ? 'bump' : 'version'; await exec('node', [resolveFrom(cwd, '@changesets/cli/bin.js'), cmd], { cwd, }); } const changedPackages = await getChangedPackages(cwd, versionsByDirectory); const mrBodyPromise = (async () => `This MR was opened by the [changesets-gitlab](https://github.com/un-ts/changesets-gitlab) GitLab CI script. When you're ready to do a release, you can merge this and ${hasPublishScript ? 'the packages will be published to npm automatically' : 'publish to npm yourself or [setup this action to publish automatically](https://github.com/un-ts/changesets-gitlab#with-publishing)'}. If you're not ready to do a release yet, that's fine, whenever you add more changesets to ${currentBranch}, this MR will be updated. ${preState ? ` ⚠️⚠️⚠️⚠️⚠️⚠️ \`${currentBranch}\` is currently in **pre mode** so this branch has prereleases rather than normal releases. If you want to exit prereleases, run \`changeset pre exit\` on \`${currentBranch}\`. ⚠️⚠️⚠️⚠️⚠️⚠️ ` : ''} # Releases ` + (await Promise.all(changedPackages.map(async (pkg) => { const changelogContents = await fs.readFile(path.join(pkg.dir, 'CHANGELOG.md'), 'utf8'); const entry = getChangelogEntry(changelogContents, pkg.packageJson.version); return { highestLevel: entry.highestLevel, private: !!pkg.packageJson.private, content: `## ${pkg.packageJson.name}@${pkg.packageJson.version}\n\n` + entry.content, }; }))) .filter(Boolean) .sort(sortTheThings) .map(x => x.content) .join('\n '))(); const finalMrTitle = `${mrTitle}${preState ? ` (${preState.tag})` : ''}`; if (!(await gitUtils.checkIfClean())) { const finalCommitMessage = `${commitMessage}${preState ? ` (${preState.tag})` : ''}`; await gitUtils.commitAll(finalCommitMessage); } await gitUtils.push(versionBranch, { force: true }); const searchResult = await api.MergeRequests.all({ projectId: context.projectId, state: 'opened', sourceBranch: versionBranch, target_branch: mrTargetBranch, maxPages: 1, perPage: 1, }); console.log(JSON.stringify(searchResult, null, 2)); if (searchResult.length === 0) { console.log(`creating merge request from ${versionBranch} to ${mrTargetBranch}.`); await api.MergeRequests.create(context.projectId, versionBranch, mrTargetBranch, finalMrTitle, { description: await mrBodyPromise, removeSourceBranch, labels, }); } else { console.log(`updating found merge request !${searchResult[0].iid}`); await api.MergeRequests.edit(context.projectId, searchResult[0].iid, { title: finalMrTitle, description: await mrBodyPromise, removeSourceBranch, labels, }); } } //# sourceMappingURL=run.js.map