From e8fe729ab9ac58a7cccdbc654afdbc7846102621 Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Fri, 9 Nov 2018 15:09:24 -0500 Subject: [PATCH] feat: update `package.json` with `npm version` --- lib/prepare.js | 24 ++- lib/update-package-version.js | 34 ----- package.json | 3 - test/integration.test.js | 23 --- test/prepare.test.js | 226 ++++++++++++++++++++++++++++ test/update-package-version.test.js | 112 -------------- 6 files changed, 244 insertions(+), 178 deletions(-) delete mode 100644 lib/update-package-version.js create mode 100644 test/prepare.test.js delete mode 100644 test/update-package-version.test.js diff --git a/lib/prepare.js b/lib/prepare.js index 6cc9a2eb..096394d8 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -1,25 +1,37 @@ const path = require('path'); const {move} = require('fs-extra'); const execa = require('execa'); -const updatePackageVersion = require('./update-package-version'); module.exports = async ({tarballDir, pkgRoot}, {cwd, env, stdout, stderr, nextRelease: {version}, logger}) => { const basePath = pkgRoot ? path.resolve(cwd, pkgRoot) : cwd; - await updatePackageVersion(version, basePath, logger); + + logger.log('Write version %s to package.json in %s', version, basePath); + + const versionResult = execa('npm', ['version', version, '--no-git-tag-version'], {cwd: basePath, env}); + versionResult.stdout.pipe( + stdout, + {end: false} + ); + versionResult.stderr.pipe( + stderr, + {end: false} + ); + + await versionResult; if (tarballDir) { logger.log('Creating npm package version %s', version); - const result = execa('npm', ['pack', basePath], {cwd, env}); - result.stdout.pipe( + const packResult = execa('npm', ['pack', basePath], {cwd, env}); + packResult.stdout.pipe( stdout, {end: false} ); - result.stderr.pipe( + packResult.stderr.pipe( stderr, {end: false} ); - const tarball = (await result).stdout.split('\n').pop(); + const tarball = (await packResult).stdout.split('\n').pop(); await move(path.resolve(cwd, tarball), path.resolve(cwd, tarballDir.trim(), tarball)); } }; diff --git a/lib/update-package-version.js b/lib/update-package-version.js deleted file mode 100644 index 26cc36f4..00000000 --- a/lib/update-package-version.js +++ /dev/null @@ -1,34 +0,0 @@ -const path = require('path'); -const parseJson = require('parse-json'); -const detectIndent = require('detect-indent'); -const detectNewline = require('detect-newline'); -const {readFile, writeJson, pathExists} = require('fs-extra'); - -const DEFAULT_INDENT = 2; -const DEFAULT_NEWLINE = '\n'; - -module.exports = async (version, basePath, logger) => { - const packagePath = path.resolve(basePath, 'package.json'); - const shrinkwrapPath = path.resolve(basePath, 'npm-shrinkwrap.json'); - const packageLockPath = path.resolve(basePath, 'package-lock.json'); - const pkg = await readFile(packagePath, 'utf8'); - - await writeJson(packagePath, {...parseJson(pkg), ...{version}}, getWriteOptions(pkg)); - logger.log('Wrote version %s to %s', version, packagePath); - - if (await pathExists(shrinkwrapPath)) { - const shrinkwrap = await readFile(shrinkwrapPath, 'utf8'); - await writeJson(shrinkwrapPath, {...parseJson(shrinkwrap), ...{version}}, getWriteOptions(shrinkwrap)); - logger.log('Wrote version %s to %s', version, shrinkwrapPath); - } - - if (await pathExists(packageLockPath)) { - const packageLock = await readFile(packageLockPath, 'utf8'); - await writeJson(packageLockPath, {...parseJson(packageLock), ...{version}}, getWriteOptions(packageLock)); - logger.log('Wrote version %s to %s', version, packageLockPath); - } -}; - -function getWriteOptions(content) { - return {spaces: detectIndent(content).indent || DEFAULT_INDENT, EOL: detectNewline(content) || DEFAULT_NEWLINE}; -} diff --git a/package.json b/package.json index e8698686..29fe8bff 100644 --- a/package.json +++ b/package.json @@ -18,15 +18,12 @@ "dependencies": { "@semantic-release/error": "^2.2.0", "aggregate-error": "^1.0.0", - "detect-indent": "^5.0.0", - "detect-newline": "^2.1.0", "execa": "^1.0.0", "fs-extra": "^7.0.0", "lodash": "^4.17.4", "nerf-dart": "^1.0.0", "normalize-url": "^4.0.0", "npm": "^6.3.0", - "parse-json": "^4.0.0", "rc": "^1.2.8", "read-pkg": "^4.0.0", "registry-auth-token": "^3.3.1" diff --git a/test/integration.test.js b/test/integration.test.js index 5f5e8a96..f5d3e6e4 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -494,29 +494,6 @@ test('Prepare the package from a sub-directory', async t => { t.false(await pathExists(path.resolve(cwd, `${pkg.name}-1.0.0.tgz`))); }); -test('Create the package in prepare step', async t => { - const cwd = tempy.directory(); - const env = npmRegistry.authEnv; - const pkg = {name: 'prepare-pkg', version: '0.0.0', publishConfig: {registry: npmRegistry.url}}; - await outputJson(path.resolve(cwd, 'package.json'), pkg); - - await t.context.m.prepare( - {npmPublish: false, tarballDir: 'tarball'}, - { - cwd, - env, - options: {}, - stdout: t.context.stdout, - stderr: t.context.stderr, - logger: t.context.logger, - nextRelease: {version: '1.0.0'}, - } - ); - - t.is((await readJson(path.resolve(cwd, 'package.json'))).version, '1.0.0'); - t.true(await pathExists(path.resolve(cwd, `tarball/${pkg.name}-1.0.0.tgz`))); -}); - test('Throw SemanticReleaseError Array if config option are not valid in prepare', async t => { const cwd = tempy.directory(); const pkg = {publishConfig: {registry: npmRegistry.url}}; diff --git a/test/prepare.test.js b/test/prepare.test.js new file mode 100644 index 00000000..3407357e --- /dev/null +++ b/test/prepare.test.js @@ -0,0 +1,226 @@ +import path from 'path'; +import test from 'ava'; +import {outputJson, readJson, outputFile, readFile, pathExists} from 'fs-extra'; +import tempy from 'tempy'; +import execa from 'execa'; +import {stub} from 'sinon'; +import {WritableStreamBuffer} from 'stream-buffers'; +import prepare from '../lib/prepare'; + +test.beforeEach(t => { + t.context.log = stub(); + t.context.logger = {log: t.context.log}; + t.context.stdout = new WritableStreamBuffer(); + t.context.stderr = new WritableStreamBuffer(); +}); + +test('Updade package.json', async t => { + const cwd = tempy.directory(); + const packagePath = path.resolve(cwd, 'package.json'); + await outputJson(packagePath, {version: '0.0.0-dev'}); + + await prepare( + {}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json has been updated + t.is((await readJson(packagePath)).version, '1.0.0'); + + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', cwd]); +}); + +test('Updade package.json and npm-shrinkwrap.json', async t => { + const cwd = tempy.directory(); + const packagePath = path.resolve(cwd, 'package.json'); + const shrinkwrapPath = path.resolve(cwd, 'npm-shrinkwrap.json'); + await outputJson(packagePath, {version: '0.0.0-dev'}); + // Create a npm-shrinkwrap.json file + await execa('npm', ['shrinkwrap'], {cwd}); + + await prepare( + {}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json and npm-shrinkwrap.json have been updated + t.is((await readJson(packagePath)).version, '1.0.0'); + t.is((await readJson(shrinkwrapPath)).version, '1.0.0'); + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', cwd]); +}); + +test('Updade package.json and package-lock.json', async t => { + const cwd = tempy.directory(); + const packagePath = path.resolve(cwd, 'package.json'); + const packageLockPath = path.resolve(cwd, 'package-lock.json'); + await outputJson(packagePath, {version: '0.0.0-dev'}); + // Create a package-lock.json file + await execa('npm', ['install'], {cwd}); + + await prepare( + {}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json and package-lock.json have been updated + t.is((await readJson(packagePath)).version, '1.0.0'); + t.is((await readJson(packageLockPath)).version, '1.0.0'); + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', cwd]); +}); + +test('Updade package.json and npm-shrinkwrap.json in a sub-directory', async t => { + const cwd = tempy.directory(); + const pkgRoot = 'dist'; + const packagePath = path.resolve(cwd, pkgRoot, 'package.json'); + const shrinkwrapPath = path.resolve(cwd, pkgRoot, 'npm-shrinkwrap.json'); + await outputJson(packagePath, {version: '0.0.0-dev'}); + // Create a npm-shrinkwrap.json file + await execa('npm', ['shrinkwrap'], {cwd: path.resolve(cwd, pkgRoot)}); + + await prepare( + {pkgRoot}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json and npm-shrinkwrap.json have been updated + t.is((await readJson(packagePath)).version, '1.0.0'); + t.is((await readJson(shrinkwrapPath)).version, '1.0.0'); + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', path.resolve(cwd, pkgRoot)]); +}); + +test('Updade package.json and package-lock.json in a sub-directory', async t => { + const cwd = tempy.directory(); + const pkgRoot = 'dist'; + const packagePath = path.resolve(cwd, pkgRoot, 'package.json'); + const packageLockPath = path.resolve(cwd, pkgRoot, 'package-lock.json'); + await outputJson(packagePath, {version: '0.0.0-dev'}); + // Create a package-lock.json file + await execa('npm', ['install'], {cwd: path.resolve(cwd, pkgRoot)}); + + await prepare( + {pkgRoot}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json and package-lock.json have been updated + t.is((await readJson(packagePath)).version, '1.0.0'); + t.is((await readJson(packageLockPath)).version, '1.0.0'); + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', path.resolve(cwd, pkgRoot)]); +}); + +test('Preserve indentation and newline', async t => { + const cwd = tempy.directory(); + const packagePath = path.resolve(cwd, 'package.json'); + await outputFile(packagePath, `{\r\n "name": "package-name",\r\n "version": "0.0.0-dev"\r\n}\r\n`); + + await prepare( + {}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json has been updated + t.is( + await readFile(packagePath, 'utf-8'), + `{\r\n "name": "package-name",\r\n "version": "1.0.0"\r\n}\r\n` + ); + + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', cwd]); +}); + +test('Use default indentation and newline if it cannot be detected', async t => { + const cwd = tempy.directory(); + const packagePath = path.resolve(cwd, 'package.json'); + await outputFile(packagePath, `{"name": "package-name","version": "0.0.0-dev"}`); + + await prepare( + {}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json has been updated + t.is(await readFile(packagePath, 'utf-8'), `{\n "name": "package-name",\n "version": "1.0.0"\n}\n`); + + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', cwd]); +}); + +test('Create the package in the "tarballDir" directory', async t => { + const cwd = tempy.directory(); + const packagePath = path.resolve(cwd, 'package.json'); + const pkg = {name: 'my-pkg', version: '0.0.0-dev'}; + await outputJson(packagePath, pkg); + + await prepare( + {tarballDir: 'tarball'}, + { + cwd, + env: {}, + stdout: t.context.stdout, + stderr: t.context.stderr, + nextRelease: {version: '1.0.0'}, + logger: t.context.logger, + } + ); + + // Verify package.json has been updated + t.is((await readJson(packagePath)).version, '1.0.0'); + + t.true(await pathExists(path.resolve(cwd, `tarball/${pkg.name}-1.0.0.tgz`))); + // Verify the logger has been called with the version updated + t.deepEqual(t.context.log.args[0], ['Write version %s to package.json in %s', '1.0.0', cwd]); +}); diff --git a/test/update-package-version.test.js b/test/update-package-version.test.js deleted file mode 100644 index f8eb3973..00000000 --- a/test/update-package-version.test.js +++ /dev/null @@ -1,112 +0,0 @@ -import path from 'path'; -import test from 'ava'; -import {outputJson, readJson, outputFile, readFile} from 'fs-extra'; -import tempy from 'tempy'; -import execa from 'execa'; -import {stub} from 'sinon'; -import updatePackageVersion from '../lib/update-package-version'; - -test.beforeEach(t => { - t.context.log = stub(); - t.context.logger = {log: t.context.log}; -}); - -test('Updade package.json', async t => { - const cwd = tempy.directory(); - const packagePath = path.resolve(cwd, 'package.json'); - await outputJson(packagePath, {version: '0.0.0-dev'}); - - await updatePackageVersion('1.0.0', cwd, t.context.logger); - - // Verify package.json has been updated - t.is((await readJson(packagePath)).version, '1.0.0'); - - // Verify the logger has been called with the version updated - t.deepEqual(t.context.log.args[0], ['Wrote version %s to %s', '1.0.0', packagePath]); -}); - -test('Updade package.json and npm-shrinkwrap.json', async t => { - const cwd = tempy.directory(); - const packagePath = path.resolve(cwd, 'package.json'); - const shrinkwrapPath = path.resolve(cwd, 'npm-shrinkwrap.json'); - await outputJson(packagePath, {version: '0.0.0-dev'}); - // Create a npm-shrinkwrap.json file - await execa('npm', ['shrinkwrap'], {cwd}); - - await updatePackageVersion('1.0.0', cwd, t.context.logger); - - // Verify package.json and npm-shrinkwrap.json have been updated - t.is((await readJson(packagePath)).version, '1.0.0'); - t.is((await readJson(shrinkwrapPath)).version, '1.0.0'); - // Verify the logger has been called with the version updated - t.deepEqual(t.context.log.args[0], ['Wrote version %s to %s', '1.0.0', packagePath]); - t.deepEqual(t.context.log.args[1], ['Wrote version %s to %s', '1.0.0', shrinkwrapPath]); -}); - -test('Updade package.json and package-lock.json', async t => { - const cwd = tempy.directory(); - const packagePath = path.resolve(cwd, 'package.json'); - const packageLockPath = path.resolve(cwd, 'package-lock.json'); - await outputJson(packagePath, {version: '0.0.0-dev'}); - // Create a npm-shrinkwrap.json file - await execa('npm', ['install'], {cwd}); - - await updatePackageVersion('1.0.0', cwd, t.context.logger); - - // Verify package.json and npm-shrinkwrap.json have been updated - t.is((await readJson(packagePath)).version, '1.0.0'); - t.is((await readJson(packageLockPath)).version, '1.0.0'); - // Verify the logger has been called with the version updated - t.deepEqual(t.context.log.args[0], ['Wrote version %s to %s', '1.0.0', packagePath]); - t.deepEqual(t.context.log.args[1], ['Wrote version %s to %s', '1.0.0', packageLockPath]); -}); - -test('Updade package.json and npm-shrinkwrap.json in a sub-directory', async t => { - const cwd = tempy.directory(); - const pkgRoot = 'dist'; - const packagePath = path.resolve(cwd, pkgRoot, 'package.json'); - const shrinkwrapPath = path.resolve(cwd, pkgRoot, 'npm-shrinkwrap.json'); - await outputJson(packagePath, {version: '0.0.0-dev'}); - // Create a npm-shrinkwrap.json file - await execa('npm', ['shrinkwrap'], {cwd: path.resolve(cwd, pkgRoot)}); - - await updatePackageVersion('1.0.0', path.resolve(cwd, pkgRoot), t.context.logger); - - // Verify package.json and npm-shrinkwrap.json have been updated - t.is((await readJson(packagePath)).version, '1.0.0'); - t.is((await readJson(path.resolve(cwd, 'dist', 'npm-shrinkwrap.json'))).version, '1.0.0'); - // Verify the logger has been called with the version updated - t.deepEqual(t.context.log.args[0], ['Wrote version %s to %s', '1.0.0', packagePath]); - t.deepEqual(t.context.log.args[1], ['Wrote version %s to %s', '1.0.0', shrinkwrapPath]); -}); - -test('Preserve indentation and newline', async t => { - const cwd = tempy.directory(); - const packagePath = path.resolve(cwd, 'package.json'); - await outputFile(packagePath, `{\r\n "name": "package-name",\r\n "version": "0.0.0-dev"\r\n}\r\n`); - - await updatePackageVersion('1.0.0', cwd, t.context.logger); - - // Verify package.json has been updated - t.is( - await readFile(packagePath, 'utf-8'), - `{\r\n "name": "package-name",\r\n "version": "1.0.0"\r\n}\r\n` - ); - - // Verify the logger has been called with the version updated - t.deepEqual(t.context.log.args[0], ['Wrote version %s to %s', '1.0.0', packagePath]); -}); - -test('Use default indentation and newline if it cannot be detected', async t => { - const cwd = tempy.directory(); - const packagePath = path.resolve(cwd, 'package.json'); - await outputFile(packagePath, `{"name": "package-name","version": "0.0.0-dev"}`); - - await updatePackageVersion('1.0.0', cwd, t.context.logger); - - // Verify package.json has been updated - t.is(await readFile(packagePath, 'utf-8'), `{\n "name": "package-name",\n "version": "1.0.0"\n}\n`); - - // Verify the logger has been called with the version updated - t.deepEqual(t.context.log.args[0], ['Wrote version %s to %s', '1.0.0', packagePath]); -});