From facdadaddb9d1816c77d5719812734549a74899b Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Tue, 21 Nov 2017 20:20:35 -0500 Subject: [PATCH] ci: Lint with XO --- bin/semantic-release.js | 3 +- lib/get-next-version.js | 8 ++-- lib/plugins/definitions.js | 3 +- package.json | 38 +++++++----------- test/get-commits.test.js | 2 +- test/git.test.js | 6 +-- test/helpers/git-utils.js | 4 +- test/helpers/mock-github.js | 2 +- test/integration.test.js | 71 ++++++++++++++++++---------------- test/plugins/normalize.test.js | 4 +- 10 files changed, 68 insertions(+), 73 deletions(-) diff --git a/bin/semantic-release.js b/bin/semantic-release.js index eb258962..647b87b3 100755 --- a/bin/semantic-release.js +++ b/bin/semantic-release.js @@ -3,6 +3,7 @@ // Bad news: We have to write plain ES5 in this file // Good news: It's the only file of the entire project +// eslint-disable-next-line no-var var semver = require('semver'); if (semver.lt(process.version, '8.0.0')) { @@ -22,7 +23,7 @@ npx is bundled with npm >= 5.4, or available via npm. More info: npm.im/npx` process.exit(1); } -// node 8+ from this point on +// Node 8+ from this point on require('../cli')().catch(() => { process.exitCode = 1; }); diff --git a/lib/get-next-version.js b/lib/get-next-version.js index f5ea6d0f..a48921b5 100644 --- a/lib/get-next-version.js +++ b/lib/get-next-version.js @@ -3,15 +3,15 @@ const SemanticReleaseError = require('@semantic-release/error'); module.exports = (type, lastRelease, logger) => { let version; - if (!lastRelease.version) { - version = '1.0.0'; - logger.log('There is no previous release, the next release version is %s', version); - } else { + if (lastRelease.version) { version = semver.inc(lastRelease.version, type); if (!version) { throw new SemanticReleaseError(`Invalid release type ${type}`, 'EINVALIDTYPE'); } logger.log('The next release version is %s', version); + } else { + version = '1.0.0'; + logger.log('There is no previous release, the next release version is %s', version); } return version; diff --git a/lib/plugins/definitions.js b/lib/plugins/definitions.js index 5b4b917d..32b547a3 100644 --- a/lib/plugins/definitions.js +++ b/lib/plugins/definitions.js @@ -7,6 +7,7 @@ const npm = require('@semantic-release/npm'); const github = require('@semantic-release/github'); const RELEASE_TYPE = ['major', 'premajor', 'minor', 'preminor', 'patch', 'prepatch', 'prerelease']; +const validatePluginConfig = conf => isString(conf) || isString(conf.path) || isFunction(conf); module.exports = { verifyConditions: { @@ -74,5 +75,3 @@ module.exports = { }, }, }; - -const validatePluginConfig = conf => isString(conf) || isString(conf.path) || isFunction(conf); diff --git a/package.json b/package.json index ada2a850..55fa7c41 100644 --- a/package.json +++ b/package.json @@ -42,14 +42,8 @@ "commitizen": "^2.9.6", "cz-conventional-changelog": "^2.0.0", "dockerode": "^2.5.2", - "eslint": "^4.7.0", "eslint-config-prettier": "^2.5.0", - "eslint-config-standard": "^10.2.1", - "eslint-plugin-import": "^2.7.0", - "eslint-plugin-node": "^5.2.0", "eslint-plugin-prettier": "^2.3.0", - "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^3.0.1", "mockserver-client": "^2.0.0", "nock": "^9.0.2", "npm-registry-couchapp": "^2.6.12", @@ -57,26 +51,14 @@ "p-map-series": "^1.0.0", "prettier": "~1.8.0", "proxyquire": "^1.8.0", - "rimraf": "^2.5.0", "sinon": "^4.0.0", - "tempy": "^0.2.1" + "tempy": "^0.2.1", + "xo": "^0.18.2" }, "engines": { "node": ">=4", "npm": ">=2" }, - "eslintConfig": { - "extends": [ - "standard", - "prettier" - ], - "plugins": [ - "prettier" - ], - "rules": { - "prettier/prettier": 2 - } - }, "files": [ "bin", "lib", @@ -127,12 +109,22 @@ "url": "git+https://github.com/semantic-release/semantic-release.git" }, "scripts": { - "clean": "rimraf coverage && rimraf .nyc_output", "cm": "git-cz", "codecov": "codecov -f coverage/coverage-final.json", - "lint": "eslint index.js cli.js lib test", - "pretest": "npm run clean && npm run lint", + "lint": "xo", + "pretest": "npm run lint", "semantic-release": "./bin/semantic-release.js", "test": "nyc ava -v" + }, + "xo": { + "extends": [ + "prettier" + ], + "plugins": [ + "prettier" + ], + "rules": { + "prettier/prettier": 2 + } } } diff --git a/test/get-commits.test.js b/test/get-commits.test.js index 7046ab1f..3366de46 100644 --- a/test/get-commits.test.js +++ b/test/get-commits.test.js @@ -1,6 +1,7 @@ import test from 'ava'; import {stub} from 'sinon'; import SemanticReleaseError from '@semantic-release/error'; +import getCommits from '../lib/get-commits'; import { gitRepo, gitCommits, @@ -11,7 +12,6 @@ import { gitLog, gitDetachedHead, } from './helpers/git-utils'; -import getCommits from '../lib/get-commits'; test.beforeEach(t => { // Save the current working diretory diff --git a/test/git.test.js b/test/git.test.js index f0f87a6c..5d193139 100644 --- a/test/git.test.js +++ b/test/git.test.js @@ -1,6 +1,6 @@ import test from 'ava'; -import {gitRepo, gitCommits, gitCheckout, gitTagVersion, gitShallowClone, gitLog} from './helpers/git-utils'; import {gitTagHead, gitCommitTag, isCommitInHistory, unshallow, gitHead} from '../lib/git'; +import {gitRepo, gitCommits, gitCheckout, gitTagVersion, gitShallowClone, gitLog} from './helpers/git-utils'; test.beforeEach(t => { // Save the current working diretory @@ -74,7 +74,7 @@ test.serial('Get the tag associated with a commit sha or "null" if the commit do // Create a git repository, set the current working directory at the root of the repo await gitRepo(); // Add commits to the master branch - let commits = await gitCommits(['First']); + const commits = await gitCommits(['First']); // Create the tag corresponding to version 1.0.0 await gitTagVersion('v1.0.0'); @@ -86,7 +86,7 @@ test.serial('Get the commit sha for a given tag or "null" if the tag does not ex // Create a git repository, set the current working directory at the root of the repo await gitRepo(); // Add commits to the master branch - let commits = await gitCommits(['First']); + const commits = await gitCommits(['First']); // Create the tag corresponding to version 1.0.0 await gitTagVersion('v1.0.0'); diff --git a/test/helpers/git-utils.js b/test/helpers/git-utils.js index d7b6f22b..6d81de53 100644 --- a/test/helpers/git-utils.js +++ b/test/helpers/git-utils.js @@ -87,14 +87,14 @@ export async function gitTagVersion(tagName, sha) { * @return {Array} The list of tags from the current git repository. */ export async function gitTags() { - return (await execa('git', ['tag'])).stdout.split('\n').filter(tag => !!tag); + return (await execa('git', ['tag'])).stdout.split('\n').filter(tag => Boolean(tag)); } /** * @return {Array} The list of commit sha from the current git repository. */ export async function gitLog() { - return (await execa('git', ['log', '--format=format:%H'])).stdout.split('\n').filter(sha => !!sha); + return (await execa('git', ['log', '--format=format:%H'])).stdout.split('\n').filter(sha => Boolean(sha)); } /** diff --git a/test/helpers/mock-github.js b/test/helpers/mock-github.js index c1d6a26b..9301f38f 100644 --- a/test/helpers/mock-github.js +++ b/test/helpers/mock-github.js @@ -7,7 +7,7 @@ import nock from 'nock'; * @param {String} [githubUrl='https://api.github.com'] The url on which to intercept http requests. * @return {Object} A `nock` object ready to respond to a github authentication request. */ -export function authenticate( +export default function authenticate( {githubToken = 'GH_TOKEN', githubUrl = 'https://api.github.com', githubApiPathPrefix = ''} = {} ) { return nock(`${githubUrl}/${githubApiPathPrefix}`, {reqheaders: {Authorization: `token ${githubToken}`}}); diff --git a/test/integration.test.js b/test/integration.test.js index 53ca9010..fc23e468 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -7,6 +7,8 @@ import registry from './helpers/registry'; import mockServer from './helpers/mockserver'; import semanticRelease from '..'; +/* eslint-disable camelcase */ + // Environment variables used with cli const env = { npm_config_registry: registry.uri, @@ -20,14 +22,14 @@ const cli = require.resolve('../bin/semantic-release'); const pluginError = require.resolve('./fixtures/plugin-error'); const pluginInheritedError = require.resolve('./fixtures/plugin-error-inherited'); -test.before(async t => { +test.before(async () => { // Start Mock Server await mockServer.start(); // Start the local NPM registry await registry.start(); }); -test.beforeEach(async t => { +test.beforeEach(t => { // Save the current process.env t.context.env = Object.assign({}, process.env); // Save the current working diretory @@ -39,7 +41,7 @@ test.beforeEach(async t => { t.context.stderr = stub(process.stderr, 'write'); }); -test.afterEach.always(async t => { +test.afterEach.always(t => { // Restore process.env process.env = Object.assign({}, t.context.env); // Restore the current working directory @@ -51,7 +53,7 @@ test.afterEach.always(async t => { t.context.stderr.restore(); }); -test.after.always(async t => { +test.after.always(async () => { await mockServer.stop(); // Stop the local NPM registry await registry.stop(); @@ -74,7 +76,7 @@ test.serial('Release patch, minor and major versions', async t => { // Create a npm-shrinkwrap.json file await execa('npm', ['shrinkwrap'], {env}); - /** No release **/ + /* No release */ let verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -88,7 +90,7 @@ test.serial('Release patch, minor and major versions', async t => { t.regex(stdout, /There are no relevant changes, so no new version is released/); t.is(code, 0); - /** Initial release **/ + /* Initial release */ let version = '1.0.0'; verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -133,7 +135,7 @@ test.serial('Release patch, minor and major versions', async t => { await mockServer.verify(createRefMock); await mockServer.verify(createReleaseMock); - /** Patch release **/ + /* Patch release */ version = '1.0.1'; verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -178,7 +180,7 @@ test.serial('Release patch, minor and major versions', async t => { await mockServer.verify(createRefMock); await mockServer.verify(createReleaseMock); - /** Minor release **/ + /* Minor release */ version = '1.1.0'; verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -223,7 +225,7 @@ test.serial('Release patch, minor and major versions', async t => { await mockServer.verify(createRefMock); await mockServer.verify(createReleaseMock); - /** Major release **/ + /* Major release */ version = '2.0.0'; verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -285,7 +287,7 @@ test.serial('Release versions from a packed git repository, using tags to determ publishConfig: {registry: registry.uri}, }); - /** Initial release **/ + /* Initial release */ let version = '1.0.0'; let verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -327,7 +329,7 @@ test.serial('Release versions from a packed git repository, using tags to determ await gitTagVersion(`v${version}`); t.log(`Create git tag v${version}`); - /** Patch release **/ + /* Patch release */ version = '1.0.1'; verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -400,7 +402,7 @@ test.serial('Create a tag as a recovery solution for "ENOTINHISTORY" error', asy publishConfig: {registry: registry.uri}, }); - /** Initial release **/ + /* Initial release */ let version = '1.0.0'; let verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, @@ -446,12 +448,12 @@ test.serial('Create a tag as a recovery solution for "ENOTINHISTORY" error', asy await gitTagVersion(`v${version}`); t.log(`Create git tag v${version}`); - /** Rewrite sha of commit used for release **/ + /* Rewrite sha of commit used for release */ t.log('Amend release commit'); const {hash} = await gitAmmendCommit('feat: Initial commit'); - /** Patch release **/ + /* Patch release */ verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, {headers: [{name: 'Authorization', values: [`token ${env.GH_TOKEN}`]}]}, @@ -473,7 +475,7 @@ test.serial('Create a tag as a recovery solution for "ENOTINHISTORY" error', asy ) ); - /** Create a tag to recover and redo release **/ + /* Create a tag to recover and redo release */ t.log(`Create git tag v${version} to recover`); await gitTagVersion(`v${version}`, hash); @@ -526,14 +528,15 @@ test.serial('Dry-run', async t => { name: packageName, version: '0.0.0-dev', repository: {url: `git+https://github.com/${owner}/${packageName}`}, + publishConfig: {registry: registry.uri}, }); - /** Initial release **/ + /* Initial release */ const version = '1.0.0'; t.log('Commit a feature'); await gitCommits(['feat: Initial commit']); t.log('$ semantic-release -d'); - let {stdout, code} = await execa(cli, ['-d'], {env}); + const {stdout, code} = await execa(cli, ['-d'], {env}); t.regex(stdout, new RegExp(`There is no previous release, the next release version is ${version}`)); t.regex(stdout, new RegExp(`Release note for version ${version}`)); t.regex(stdout, /Initial commit/); @@ -557,12 +560,12 @@ test.serial('Pass options via CLI arguments', async t => { publishConfig: {registry: registry.uri}, }); - /** Initial release **/ - let version = '1.0.0'; + /* Initial release */ + const version = '1.0.0'; t.log('Commit a feature'); await gitCommits(['feat: Initial commit']); t.log('$ semantic-release'); - let {stdout, code} = await execa( + const {stdout, code} = await execa( cli, ['--verify-conditions', '@semantic-release/npm', '--publish', '@semantic-release/npm', '--debug'], {env} @@ -574,7 +577,7 @@ test.serial('Pass options via CLI arguments', async t => { t.is((await readJson('./package.json')).version, version); // Retrieve the published package from the registry and check version and gitHead - let [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec( + const [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec( (await execa('npm', ['show', packageName, 'version', 'gitHead'], {env})).stdout ); t.is(releasedVersion, version); @@ -597,19 +600,19 @@ test.serial('Run via JS API', async t => { publishConfig: {registry: registry.uri}, }); - /** Initial release **/ - let version = '1.0.0'; - let verifyMock = await mockServer.mock( + /* Initial release */ + const version = '1.0.0'; + const verifyMock = await mockServer.mock( `/repos/${owner}/${packageName}`, {headers: [{name: 'Authorization', values: [`token ${githubToken}`]}]}, {body: {permissions: {push: true}}, method: 'GET'} ); - let createRefMock = await mockServer.mock( + const createRefMock = await mockServer.mock( `/repos/${owner}/${packageName}/git/refs`, {body: {ref: `refs/tags/v${version}`}, headers: [{name: 'Authorization', values: [`token ${githubToken}`]}]}, {body: {ref: `refs/tags/${version}`}} ); - let createReleaseMock = await mockServer.mock( + const createReleaseMock = await mockServer.mock( `/repos/${owner}/${packageName}/releases`, { body: {tag_name: `v${version}`, target_commitish: 'master', name: `v${version}`}, @@ -636,7 +639,7 @@ test.serial('Run via JS API', async t => { t.is((await readJson('./package.json')).version, version); // Retrieve the published package from the registry and check version and gitHead - let [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec( + const [, releasedVersion, releasedGitHead] = /^version = '(.+)'\s+gitHead = '(.+)'$/.exec( (await execa('npm', ['show', packageName, 'version', 'gitHead'], {env})).stdout ); t.is(releasedVersion, version); @@ -662,11 +665,11 @@ test.serial('Log unexpected errors from plugins and exit with 1', async t => { release: {verifyConditions: pluginError}, }); - /** Initial release **/ + /* Initial release */ t.log('Commit a feature'); await gitCommits(['feat: Initial commit']); t.log('$ semantic-release'); - let {stderr, code} = await execa(cli, [], {env, reject: false}); + const {stderr, code} = await execa(cli, [], {env, reject: false}); // Verify the type and message are logged t.regex(stderr, /Error: a/); // Verify the the stacktrace is logged @@ -690,11 +693,11 @@ test.serial('Log errors inheriting SemanticReleaseError and exit with 0', async release: {verifyConditions: pluginInheritedError}, }); - /** Initial release **/ + /* Initial release */ t.log('Commit a feature'); await gitCommits(['feat: Initial commit']); t.log('$ semantic-release'); - let {stdout, code} = await execa(cli, [], {env, reject: false}); + const {stdout, code} = await execa(cli, [], {env, reject: false}); // Verify the type and message are logged t.regex(stdout, /EINHERITED Inherited error/); t.is(code, 0); @@ -702,21 +705,21 @@ test.serial('Log errors inheriting SemanticReleaseError and exit with 0', async test.serial('CLI returns error code and prints help if called with a command', async t => { t.log('$ semantic-release pre'); - let {stdout, code} = await execa(cli, ['pre'], {env, reject: false}); + const {stdout, code} = await execa(cli, ['pre'], {env, reject: false}); t.regex(stdout, /Usage: semantic-release/); t.is(code, 1); }); test.serial('CLI prints help if called with --help', async t => { t.log('$ semantic-release --help'); - let {stdout, code} = await execa(cli, ['--help'], {env}); + const {stdout, code} = await execa(cli, ['--help'], {env}); t.regex(stdout, /Usage: semantic-release/); t.is(code, 0); }); test.serial('CLI returns error code with invalid option', async t => { t.log('$ semantic-release --unknown-option'); - let {stderr, code} = await execa(cli, ['--unknown-option'], {env, reject: false}); + const {stderr, code} = await execa(cli, ['--unknown-option'], {env, reject: false}); t.regex(stderr, /unknown option/); t.is(code, 1); }); diff --git a/test/plugins/normalize.test.js b/test/plugins/normalize.test.js index 22f2ec3d..67f4c42c 100644 --- a/test/plugins/normalize.test.js +++ b/test/plugins/normalize.test.js @@ -84,7 +84,7 @@ test('Prevent plugins to modify its input', async t => { t.is(input.param.subParam, 'originalSubParam'); }); -test('Return noop if the plugin is not defined', async t => { +test('Return noop if the plugin is not defined', t => { const plugin = normalize(); t.is(plugin, noop); @@ -106,7 +106,7 @@ test('Always pass a defined "pluginConfig" for plugin defined with path', async t.deepEqual(pluginResult.pluginConfig, {}); }); -test('Throws an error if the plugin return an object without the expected plugin function', async t => { +test('Throws an error if the plugin return an object without the expected plugin function', t => { const error = t.throws(() => normalize('inexistantPlugin', './test/fixtures/multi-plugin', t.context.logger)); t.is(