From c1f4142bc4845c83b1e82d4c5148811742ab405e Mon Sep 17 00:00:00 2001 From: Eugene Date: Thu, 19 Jan 2023 23:45:31 +0300 Subject: [PATCH 1/2] feat(init): add pnpm support (#915) pnpm reuses options available for npm, except `force` re: #893, re #858 --- README.md | 9 +- src/commitizen/adapter.js | 76 +++++++------- src/commitizen/init.js | 17 ++-- test/tests/init.js | 204 ++++++++++++++++++++------------------ 4 files changed, 157 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index 2dc5464a..e0c0a41e 100644 --- a/README.md +++ b/README.md @@ -58,13 +58,14 @@ npm install commitizen -g Next, initialize your project to use the cz-conventional-changelog adapter by typing: ```sh +# npm commitizen init cz-conventional-changelog --save-dev --save-exact -``` - -Or if you are using Yarn: -```sh +# yarn commitizen init cz-conventional-changelog --yarn --dev --exact + +# pnpm +commitizen init cz-conventional-changelog --pnpm --save-dev --save-exact ``` Note that if you want to force install over the top of an old adapter, you can apply the `--force` argument. For more information on this, just run `commitizen help`. diff --git a/src/commitizen/adapter.js b/src/commitizen/adapter.js index 8818615b..b3150c40 100644 --- a/src/commitizen/adapter.js +++ b/src/commitizen/adapter.js @@ -11,12 +11,10 @@ export { addPathToAdapterConfig, getNearestNodeModulesDirectory, getNearestProjectRootDirectory, - getNpmInstallStringMappings, + getInstallStringMappings, getPrompter, - generateNpmInstallAdapterCommand, + generateInstallAdapterCommand, resolveAdapterPath, - getYarnAddStringMappings, - generateYarnAddAdapterCommand, getGitRootPath, }; @@ -55,40 +53,32 @@ function addPathToAdapterConfig (cliPath, repoPath, adapterNpmName) { fs.writeFileSync(packageJsonPath, JSON.stringify(newPackageJsonContent, null, indent) + '\n'); } -/** - * Generates an npm install command given a map of strings and a package name +/* + * Get additional options for install command */ -function generateNpmInstallAdapterCommand (stringMappings, adapterNpmName) { - - // Start with an initial npm install command - let installAdapterCommand = `npm install ${adapterNpmName}`; +function getInstallOptions(stringMappings) { + return Array.from(stringMappings.values()).filter(Boolean).join(" ") +} - // Append the neccesary arguments to it based on user preferences - for (let value of stringMappings.values()) { - if (value) { - installAdapterCommand = installAdapterCommand + ' ' + value; - } - } +/* + * Get specific install command for passed package manager + */ +function getInstallCommand(packageManager) { + const fallbackCommand = 'install'; + const commandByPackageManager = { + npm: 'install', + yarn: 'add', + pnpm: 'add', + }; - return installAdapterCommand; + return commandByPackageManager[packageManager] || fallbackCommand; } /** - * Generates an yarn add command given a map of strings and a package name + * Generates an npm install command given a map of strings and a package name */ -function generateYarnAddAdapterCommand (stringMappings, adapterNpmName) { - - // Start with an initial yarn add command - let installAdapterCommand = `yarn add ${adapterNpmName}`; - - // Append the necessary arguments to it based on user preferences - for (let value of stringMappings.values()) { - if (value) { - installAdapterCommand = installAdapterCommand + ' ' + value; - } - } - - return installAdapterCommand; +function generateInstallAdapterCommand(stringMappings, adapterNpmName, packageManager = "npm") { + return `${packageManager} ${getInstallCommand(packageManager)} ${adapterNpmName} ${getInstallOptions(stringMappings)}`; } /** @@ -117,24 +107,28 @@ function getNearestProjectRootDirectory (repoPath, options) { } /** - * Gets a map of arguments where the value is the corresponding npm strings + * Gets a map of arguments where the value is the corresponding (to passed package manager) string */ -function getNpmInstallStringMappings (save, saveDev, saveExact, force) { - return new Map() - .set('save', (save && !saveDev) ? '--save' : undefined) +function getInstallStringMappings({ save, dev, saveDev, exact, saveExact, force }, packageManager) { + const npm = new Map() + .set('save', save && !saveDev ? '--save' : undefined) .set('saveDev', saveDev ? '--save-dev' : undefined) .set('saveExact', saveExact ? '--save-exact' : undefined) .set('force', force ? '--force' : undefined); -} -/** - * Gets a map of arguments where the value is the corresponding yarn strings - */ -function getYarnAddStringMappings (dev, exact, force) { - return new Map() + const yarn = new Map() .set('dev', dev ? '--dev' : undefined) .set('exact', exact ? '--exact' : undefined) .set('force', force ? '--force' : undefined); + + const pnpm = new Map() + .set('save', save && !saveDev ? '--save-prod' : undefined) + .set('dev', saveDev ? '--save-dev' : undefined) + .set('exact', saveExact ? '--save-exact' : undefined); + + const map = { npm, yarn, pnpm }; + + return map[packageManager] || npm; } /** diff --git a/src/commitizen/init.js b/src/commitizen/init.js index 91ec5b7d..f4769c9b 100644 --- a/src/commitizen/init.js +++ b/src/commitizen/init.js @@ -5,10 +5,8 @@ import * as adapter from './adapter'; let { addPathToAdapterConfig, - generateNpmInstallAdapterCommand, - getNpmInstallStringMappings, - generateYarnAddAdapterCommand, - getYarnAddStringMappings, + generateInstallAdapterCommand, + getInstallStringMappings, } = adapter; export default init; @@ -43,6 +41,8 @@ const defaultInitOptions = { yarn: false, dev: true, exact: false, // should add trailing comma, thus next developer doesn't got blamed for this line + + pnpm: false, // reuses `save`, `saveDev`, `saveExact` }; /** @@ -56,6 +56,7 @@ function init (repoPath, adapterNpmName, { yarn = false, dev = false, exact = false, + pnpm = false, includeCommitizen = false } = defaultInitOptions) { @@ -65,13 +66,15 @@ function init (repoPath, adapterNpmName, { // Load the current adapter config let adapterConfig = loadAdapterConfig(repoPath); + const packageManager = yarn ? 'yarn' : pnpm ? 'pnpm' : 'npm'; + // Get the npm string mappings based on the arguments provided - let stringMappings = yarn ? getYarnAddStringMappings(dev, exact, force) : getNpmInstallStringMappings(save, saveDev, saveExact, force); + const stringMappings = getInstallStringMappings({ save, dev, saveDev, saveExact, force }, packageManager); // Generate a string that represents the npm install command - let installAdapterCommand = yarn ? generateYarnAddAdapterCommand(stringMappings, adapterNpmName) : generateNpmInstallAdapterCommand(stringMappings, adapterNpmName); + const installAdapterCommand = generateInstallAdapterCommand(stringMappings, adapterNpmName, packageManager); - let installCommitizenCommand = yarn ? generateYarnAddAdapterCommand(stringMappings, "commitizen") : generateNpmInstallAdapterCommand(stringMappings, "commitizen"); + const installCommitizenCommand = generateInstallAdapterCommand(stringMappings, 'commitizen', packageManager); // Check for previously installed adapters if (adapterConfig && adapterConfig.path && adapterConfig.path.length > 0 && !force) { diff --git a/test/tests/init.js b/test/tests/init.js index 4d465e43..454016bb 100644 --- a/test/tests/init.js +++ b/test/tests/init.js @@ -173,130 +173,140 @@ describe('init', function () { }); - it('installs an adapter with --yarn', function () { + const supportedPackageManagers = ['yarn', 'pnpm']; - this.timeout(config.maxTimeout); // this could take a while + supportedPackageManagers.forEach((packageManger) => { + describe(`alternative package managers: ${packageManger}`, () => { + it(`installs an adapter with ${packageManger}`, function () { + this.timeout(config.maxTimeout); // this could take a while - // SETUP + // SETUP - // Install an adapter - commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { yarn: true }); + // Install an adapter + commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true }); - // TEST + // TEST - // Check resulting json - let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - expect(packageJson).to.have.nested.property('dependencies.cz-conventional-changelog'); + // Check resulting json + let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); + if (packageManger === 'yarn') { + expect(packageJson).to.have.nested.property('dependencies.cz-conventional-changelog'); + } else { + expect(packageJson).to.have.nested.property('devDependencies.cz-conventional-changelog'); + } + }); - }); + it(`installs an adapter with ${packageManger} --dev`, function () { + this.timeout(config.maxTimeout); // this could take a while - it('installs an adapter with --yarn --dev', function () { + // SETUP - this.timeout(config.maxTimeout); // this could take a while + // Install an adapter + commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true }); - // SETUP + // TEST - // Install an adapter - commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { yarn: true, dev: true }); + // Check resulting json + let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); + expect(packageJson).to.have.nested.property('devDependencies.cz-conventional-changelog'); + }); - // TEST - - // Check resulting json - let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - expect(packageJson).to.have.nested.property('devDependencies.cz-conventional-changelog'); + it(`errors (with ${packageManger}) on previously installed adapter`, function () { + this.timeout(config.maxTimeout); // this could take a while - }); + // SETUP - it('errors (with --yarn) on previously installed adapter', function () { + // Add a first adapter + commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true }); - this.timeout(config.maxTimeout); // this could take a while + // TEST + // Adding a second adapter + expect(function () { + commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { [packageManger]: true, dev: true }); + }).to.throw(/already configured/); - // SETUP + // Check resulting json + let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); + expect(packageJson).not.to.have.nested.property('devDependencies', 'cz-jira-smart-commit'); + expect(packageJson).to.have.nested.property( + 'config.commitizen.path', + './node_modules/cz-conventional-changelog' + ); + // TODO: Eventually may need to offer both path and package keys. package = npm package name + // Path for local development + }); - // Add a first adapter - commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { yarn: true, dev: true }); + it(`succeeds (with ${packageManger}) if force is true`, function () { + this.timeout(config.maxTimeout); // this could take a while - // TEST - // Adding a second adapter - expect(function () { - commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { yarn: true, dev: true }); - }).to.throw(/already configured/); + // SETUP - // Check resulting json - let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - expect(packageJson).not.to.have.nested.property('devDependencies', 'cz-jira-smart-commit'); - expect(packageJson).to.have.nested.property('config.commitizen.path', './node_modules/cz-conventional-changelog'); - // TODO: Eventually may need to offer both path and package keys. package = npm package name - // Path for local development - }); + // Add a first adapter + commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true }); - it('succeeds (with --yarn) if force is true', function () { + // TEST - this.timeout(config.maxTimeout); // this could take a while + // Adding a second adapter + expect(function () { + commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { + [packageManger]: true, + dev: true, + force: true, + }); + }).to.not.throw(); - // SETUP + let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); + expect(packageJson.devDependencies).to.have.property('cz-jira-smart-commit'); + expect(packageJson).to.have.nested.property('config.commitizen.path', './node_modules/cz-jira-smart-commit'); + }); - // Add a first adapter - commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { yarn: true, dev: true }); + it(`installs (with ${packageManger}) an adapter without --save-exact`, function () { + this.timeout(config.maxTimeout); // this could take a while - // TEST + // SETUP - // Adding a second adapter - expect(function () { - commitizenInit(config.paths.endUserRepo, 'cz-jira-smart-commit', { yarn: true, dev: true, force: true }); - }).to.not.throw(); + // Add a first adapter + commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { [packageManger]: true, dev: true }); + let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - expect(packageJson.devDependencies).to.have.property('cz-jira-smart-commit'); - expect(packageJson).to.have.nested.property('config.commitizen.path', './node_modules/cz-jira-smart-commit'); + // TEST + expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog'); + let range = packageJson.devDependencies['cz-conventional-changelog']; - }); - - it('installs (with --yarn) an adapter without --save-exact', function () { - - this.timeout(config.maxTimeout); // this could take a while - - // SETUP - - // Add a first adapter - commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { yarn: true, dev: true }); - let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - - // TEST - expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog'); - let range = packageJson.devDependencies['cz-conventional-changelog']; - - // It should satisfy the requirements of a range - expect(semver.validRange(range)).to.not.equal(null); - - // // But you CAN NOT increment a range - // expect(semver.inc(range, 'major')).to.equal(null); - // TODO: We need to figure out how to check if the repo has save exact set - // in the config before we can re-enable this. The --save-exact setting - // in our package.json breaks this test - - }); - - it('installs an adapter with --yarn --exact', function () { - - this.timeout(config.maxTimeout); // this could take a while - - // SETUP - - // Add a first adapter - commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { yarn: true, dev: true, exact: true }); - let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); - - // TEST - expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog'); - let range = packageJson.devDependencies['cz-conventional-changelog']; - - // It should satisfy the requirements of a range - expect(semver.validRange(range)).to.not.equal(null); - - // But you CAN increment a single version - expect(semver.inc(range, 'major')).not.to.equal(null); + // It should satisfy the requirements of a range + expect(semver.validRange(range)).to.not.equal(null); + + // // But you CAN NOT increment a range + // expect(semver.inc(range, 'major')).to.equal(null); + // TODO: We need to figure out how to check if the repo has save exact set + // in the config before we can re-enable this. The --save-exact setting + // in our package.json breaks this test + }); + + it(`installs an adapter with ${packageManger} --exact`, function () { + this.timeout(config.maxTimeout); // this could take a while + + // SETUP + + // Add a first adapter + commitizenInit(config.paths.endUserRepo, 'cz-conventional-changelog', { + [packageManger]: true, + dev: true, + exact: true, + }); + let packageJson = util.getParsedPackageJsonFromPath(config.paths.endUserRepo); + // TEST + expect(packageJson.devDependencies).to.have.property('cz-conventional-changelog'); + let range = packageJson.devDependencies['cz-conventional-changelog']; + + // It should satisfy the requirements of a range + expect(semver.validRange(range)).to.not.equal(null); + + // But you CAN increment a single version + expect(semver.inc(range, 'major')).not.to.equal(null); + }); + }); }); }); From 4100234b9a7f500ea2c0604097f749bcbda97ffe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Jan 2023 23:59:46 +0000 Subject: [PATCH 2/2] chore(deps) Update actions/setup-node action to v3 --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e03b06dd..7e570b0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/setup-node@v3 with: cache: npm node-version: lts/*