style: prettier (#2624)

This commit is contained in:
Gregor Martynus
2022-11-23 16:02:51 -08:00
committed by GitHub
parent 8a0d8be51f
commit d13ea9280e
54 changed files with 3129 additions and 15324 deletions
+177 -171
View File
@@ -1,19 +1,19 @@
import test from 'ava';
import {escapeRegExp} from 'lodash-es';
import * as td from 'testdouble';
import {stub} from 'sinon';
import {SECRET_REPLACEMENT} from '../lib/definitions/constants.js';
import test from "ava";
import { escapeRegExp } from "lodash-es";
import * as td from "testdouble";
import { stub } from "sinon";
import { SECRET_REPLACEMENT } from "../lib/definitions/constants.js";
let previousArgv;
let previousEnv;
test.beforeEach((t) => {
t.context.logs = '';
t.context.errors = '';
t.context.stdout = stub(process.stdout, 'write').callsFake((value) => {
t.context.logs = "";
t.context.errors = "";
t.context.stdout = stub(process.stdout, "write").callsFake((value) => {
t.context.logs += value.toString();
});
t.context.stderr = stub(process.stderr, 'write').callsFake((value) => {
t.context.stderr = stub(process.stderr, "write").callsFake((value) => {
t.context.errors += value.toString();
});
@@ -31,196 +31,202 @@ test.afterEach.always((t) => {
td.reset();
});
test.serial('Pass options to semantic-release API', async (t) => {
test.serial("Pass options to semantic-release API", async (t) => {
const argv = [
'',
'',
'-b',
'master',
'next',
'-r',
'https://github/com/owner/repo.git',
'-t',
"",
"",
"-b",
"master",
"next",
"-r",
"https://github/com/owner/repo.git",
"-t",
`v\${version}`,
'-p',
'plugin1',
'plugin2',
'-e',
'config1',
'config2',
'--verify-conditions',
'condition1',
'condition2',
'--analyze-commits',
'analyze',
'--verify-release',
'verify1',
'verify2',
'--generate-notes',
'notes',
'--prepare',
'prepare1',
'prepare2',
'--publish',
'publish1',
'publish2',
'--success',
'success1',
'success2',
'--fail',
'fail1',
'fail2',
'--debug',
'-d',
"-p",
"plugin1",
"plugin2",
"-e",
"config1",
"config2",
"--verify-conditions",
"condition1",
"condition2",
"--analyze-commits",
"analyze",
"--verify-release",
"verify1",
"verify2",
"--generate-notes",
"notes",
"--prepare",
"prepare1",
"prepare2",
"--publish",
"publish1",
"publish2",
"--success",
"success1",
"success2",
"--fail",
"fail1",
"fail2",
"--debug",
"-d",
];
const index = await td.replaceEsm('../index.js');
const index = await td.replaceEsm("../index.js");
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
td.verify(index.default({
branches: ['master', 'next'],
b: ['master', 'next'],
'repository-url': 'https://github/com/owner/repo.git',
repositoryUrl: 'https://github/com/owner/repo.git',
r: 'https://github/com/owner/repo.git',
'tag-format': `v\${version}`,
tagFormat: `v\${version}`,
t: `v\${version}`,
plugins: ['plugin1', 'plugin2'],
p: ['plugin1', 'plugin2'],
extends: ['config1', 'config2'],
e: ['config1', 'config2'],
'dry-run': true,
dryRun: true,
d: true,
verifyConditions: ['condition1', 'condition2'],
'verify-conditions': ['condition1', 'condition2'],
analyzeCommits: 'analyze',
'analyze-commits': 'analyze',
verifyRelease: ['verify1', 'verify2'],
'verify-release': ['verify1', 'verify2'],
generateNotes: ['notes'],
'generate-notes': ['notes'],
prepare: ['prepare1', 'prepare2'],
publish: ['publish1', 'publish2'],
success: ['success1', 'success2'],
fail: ['fail1', 'fail2'],
debug: true,
_: [],
'$0': ''
}));
td.verify(
index.default({
branches: ["master", "next"],
b: ["master", "next"],
"repository-url": "https://github/com/owner/repo.git",
repositoryUrl: "https://github/com/owner/repo.git",
r: "https://github/com/owner/repo.git",
"tag-format": `v\${version}`,
tagFormat: `v\${version}`,
t: `v\${version}`,
plugins: ["plugin1", "plugin2"],
p: ["plugin1", "plugin2"],
extends: ["config1", "config2"],
e: ["config1", "config2"],
"dry-run": true,
dryRun: true,
d: true,
verifyConditions: ["condition1", "condition2"],
"verify-conditions": ["condition1", "condition2"],
analyzeCommits: "analyze",
"analyze-commits": "analyze",
verifyRelease: ["verify1", "verify2"],
"verify-release": ["verify1", "verify2"],
generateNotes: ["notes"],
"generate-notes": ["notes"],
prepare: ["prepare1", "prepare2"],
publish: ["publish1", "publish2"],
success: ["success1", "success2"],
fail: ["fail1", "fail2"],
debug: true,
_: [],
$0: "",
})
);
t.is(exitCode, 0);
});
test.serial('Pass options to semantic-release API with alias arguments', async (t) => {
test.serial("Pass options to semantic-release API with alias arguments", async (t) => {
const argv = [
'',
'',
'--branches',
'master',
'--repository-url',
'https://github/com/owner/repo.git',
'--tag-format',
"",
"",
"--branches",
"master",
"--repository-url",
"https://github/com/owner/repo.git",
"--tag-format",
`v\${version}`,
'--plugins',
'plugin1',
'plugin2',
'--extends',
'config1',
'config2',
'--dry-run',
"--plugins",
"plugin1",
"plugin2",
"--extends",
"config1",
"config2",
"--dry-run",
];
const index = await td.replaceEsm('../index.js');
const index = await td.replaceEsm("../index.js");
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
td.verify(index.default({
branches: ['master'],
b: ['master'],
'repository-url': 'https://github/com/owner/repo.git',
repositoryUrl: 'https://github/com/owner/repo.git',
r: 'https://github/com/owner/repo.git',
'tag-format': `v\${version}`,
tagFormat: `v\${version}`,
t: `v\${version}`,
plugins: ['plugin1', 'plugin2'],
p: ['plugin1', 'plugin2'],
extends: ['config1', 'config2'],
e: ['config1', 'config2'],
'dry-run': true,
dryRun: true,
d: true,
_: [],
'$0': ''
}));
td.verify(
index.default({
branches: ["master"],
b: ["master"],
"repository-url": "https://github/com/owner/repo.git",
repositoryUrl: "https://github/com/owner/repo.git",
r: "https://github/com/owner/repo.git",
"tag-format": `v\${version}`,
tagFormat: `v\${version}`,
t: `v\${version}`,
plugins: ["plugin1", "plugin2"],
p: ["plugin1", "plugin2"],
extends: ["config1", "config2"],
e: ["config1", "config2"],
"dry-run": true,
dryRun: true,
d: true,
_: [],
$0: "",
})
);
t.is(exitCode, 0);
});
test.serial('Pass unknown options to semantic-release API', async (t) => {
const argv = ['', '', '--bool', '--first-option', 'value1', '--second-option', 'value2', '--second-option', 'value3'];
const index = await td.replaceEsm('../index.js');
test.serial("Pass unknown options to semantic-release API", async (t) => {
const argv = ["", "", "--bool", "--first-option", "value1", "--second-option", "value2", "--second-option", "value3"];
const index = await td.replaceEsm("../index.js");
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
td.verify(index.default({
bool: true,
firstOption: 'value1',
'first-option': 'value1',
secondOption: ['value2', 'value3'],
'second-option': ['value2', 'value3'],
_: [],
'$0': ''
}));
td.verify(
index.default({
bool: true,
firstOption: "value1",
"first-option": "value1",
secondOption: ["value2", "value3"],
"second-option": ["value2", "value3"],
_: [],
$0: "",
})
);
t.is(exitCode, 0);
});
test.serial('Pass empty Array to semantic-release API for list option set to "false"', async (t) => {
const argv = ['', '', '--publish', 'false'];
const index = await td.replaceEsm('../index.js');
const argv = ["", "", "--publish", "false"];
const index = await td.replaceEsm("../index.js");
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
td.verify(index.default({publish: [], _: [], '$0': ''}));
td.verify(index.default({ publish: [], _: [], $0: "" }));
t.is(exitCode, 0);
});
test.serial('Do not set properties in option for which arg is not in command line', async (t) => {
test.serial("Do not set properties in option for which arg is not in command line", async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '-b', 'master'];
await td.replaceEsm('../index.js', null, run);
const argv = ["", "", "-b", "master"];
await td.replaceEsm("../index.js", null, run);
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
await cli();
t.false('ci' in run.args[0][0]);
t.false('d' in run.args[0][0]);
t.false('dry-run' in run.args[0][0]);
t.false('debug' in run.args[0][0]);
t.false('r' in run.args[0][0]);
t.false('t' in run.args[0][0]);
t.false('p' in run.args[0][0]);
t.false('e' in run.args[0][0]);
t.false("ci" in run.args[0][0]);
t.false("d" in run.args[0][0]);
t.false("dry-run" in run.args[0][0]);
t.false("debug" in run.args[0][0]);
t.false("r" in run.args[0][0]);
t.false("t" in run.args[0][0]);
t.false("p" in run.args[0][0]);
t.false("e" in run.args[0][0]);
});
test.serial('Display help', async (t) => {
test.serial("Display help", async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '--help'];
await td.replaceEsm('../index.js', null, run);
const argv = ["", "", "--help"];
await td.replaceEsm("../index.js", null, run);
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
@@ -228,12 +234,12 @@ test.serial('Display help', async (t) => {
t.is(exitCode, 0);
});
test.serial('Return error exitCode and prints help if called with a command', async (t) => {
test.serial("Return error exitCode and prints help if called with a command", async (t) => {
const run = stub().resolves(true);
const argv = ['', '', 'pre'];
await td.replaceEsm('../index.js', null, run);
const argv = ["", "", "pre"];
await td.replaceEsm("../index.js", null, run);
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
@@ -242,12 +248,12 @@ test.serial('Return error exitCode and prints help if called with a command', as
t.is(exitCode, 1);
});
test.serial('Return error exitCode if multiple plugin are set for single plugin', async (t) => {
test.serial("Return error exitCode if multiple plugin are set for single plugin", async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '--analyze-commits', 'analyze1', 'analyze2'];
await td.replaceEsm('../index.js', null, run);
const argv = ["", "", "--analyze-commits", "analyze1", "analyze2"];
await td.replaceEsm("../index.js", null, run);
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
@@ -256,12 +262,12 @@ test.serial('Return error exitCode if multiple plugin are set for single plugin'
t.is(exitCode, 1);
});
test.serial('Return error exitCode if semantic-release throw error', async (t) => {
const argv = ['', ''];
const index = await td.replaceEsm('../index.js');
td.when(index.default({_: [], '$0': ''})).thenReject(new Error('semantic-release error'));
test.serial("Return error exitCode if semantic-release throw error", async (t) => {
const argv = ["", ""];
const index = await td.replaceEsm("../index.js");
td.when(index.default({ _: [], $0: "" })).thenReject(new Error("semantic-release error"));
process.argv = argv;
const cli = (await import('../cli.js')).default;
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
@@ -269,14 +275,14 @@ test.serial('Return error exitCode if semantic-release throw error', async (t) =
t.is(exitCode, 1);
});
test.serial('Hide sensitive environment variable values from the logs', async (t) => {
const env = {MY_TOKEN: 'secret token'};
const argv = ['', ''];
const index = await td.replaceEsm('../index.js');
td.when(index.default({_: [], '$0': ''})).thenReject(new Error(`Throw error: Exposing token ${env.MY_TOKEN}`));
test.serial("Hide sensitive environment variable values from the logs", async (t) => {
const env = { MY_TOKEN: "secret token" };
const argv = ["", ""];
const index = await td.replaceEsm("../index.js");
td.when(index.default({ _: [], $0: "" })).thenReject(new Error(`Throw error: Exposing token ${env.MY_TOKEN}`));
process.argv = argv;
process.env = {...process.env, ...env};
const cli = (await import('../cli.js')).default;
process.env = { ...process.env, ...env };
const cli = (await import("../cli.js")).default;
const exitCode = await cli();
+29 -29
View File
@@ -1,39 +1,39 @@
import test from 'ava';
import {stub} from 'sinon';
import getCommits from '../lib/get-commits.js';
import {gitCommits, gitDetachedHead, gitRepo} from './helpers/git-utils.js';
import test from "ava";
import { stub } from "sinon";
import getCommits from "../lib/get-commits.js";
import { gitCommits, gitDetachedHead, gitRepo } from "./helpers/git-utils.js";
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = stub();
t.context.error = stub();
t.context.logger = {log: t.context.log, error: t.context.error};
t.context.logger = { log: t.context.log, error: t.context.error };
});
test('Get all commits when there is no last release', async (t) => {
test("Get all commits when there is no last release", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First', 'Second'], {cwd});
const commits = await gitCommits(["First", "Second"], { cwd });
// Retrieve the commits with the commits module
const result = await getCommits({cwd, lastRelease: {}, logger: t.context.logger});
const result = await getCommits({ cwd, lastRelease: {}, logger: t.context.logger });
// Verify the commits created and retrieved by the module are identical
t.is(result.length, 2);
t.deepEqual(result, commits);
});
test('Get all commits since gitHead (from lastRelease)', async (t) => {
test("Get all commits since gitHead (from lastRelease)", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First', 'Second', 'Third'], {cwd});
const commits = await gitCommits(["First", "Second", "Third"], { cwd });
// Retrieve the commits with the commits module, since commit 'First'
const result = await getCommits({
cwd,
lastRelease: {gitHead: commits[commits.length - 1].hash},
lastRelease: { gitHead: commits[commits.length - 1].hash },
logger: t.context.logger,
});
@@ -42,18 +42,18 @@ test('Get all commits since gitHead (from lastRelease)', async (t) => {
t.deepEqual(result, commits.slice(0, 2));
});
test('Get all commits since gitHead (from lastRelease) on a detached head repo', async (t) => {
test("Get all commits since gitHead (from lastRelease) on a detached head repo", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
let { cwd, repositoryUrl } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First', 'Second', 'Third'], {cwd});
const commits = await gitCommits(["First", "Second", "Third"], { cwd });
// Create a detached head repo at commit 'feat: Second'
cwd = await gitDetachedHead(repositoryUrl, commits[1].hash);
// Retrieve the commits with the commits module, since commit 'First'
const result = await getCommits({
cwd,
lastRelease: {gitHead: commits[commits.length - 1].hash},
lastRelease: { gitHead: commits[commits.length - 1].hash },
logger: t.context.logger,
});
@@ -66,17 +66,17 @@ test('Get all commits since gitHead (from lastRelease) on a detached head repo',
t.truthy(result[0].committer.name);
});
test('Get all commits between lastRelease.gitHead and a shas', async (t) => {
test("Get all commits between lastRelease.gitHead and a shas", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First', 'Second', 'Third'], {cwd});
const commits = await gitCommits(["First", "Second", "Third"], { cwd });
// Retrieve the commits with the commits module, between commit 'First' and 'Third'
const result = await getCommits({
cwd,
lastRelease: {gitHead: commits[commits.length - 1].hash},
nextRelease: {gitHead: commits[1].hash},
lastRelease: { gitHead: commits[commits.length - 1].hash },
nextRelease: { gitHead: commits[1].hash },
logger: t.context.logger,
});
@@ -85,16 +85,16 @@ test('Get all commits between lastRelease.gitHead and a shas', async (t) => {
t.deepEqual(result, commits.slice(1, -1));
});
test('Return empty array if lastRelease.gitHead is the last commit', async (t) => {
test("Return empty array if lastRelease.gitHead is the last commit", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First', 'Second'], {cwd});
const commits = await gitCommits(["First", "Second"], { cwd });
// Retrieve the commits with the commits module, since commit 'Second' (therefore none)
const result = await getCommits({
cwd,
lastRelease: {gitHead: commits[0].hash},
lastRelease: { gitHead: commits[0].hash },
logger: t.context.logger,
});
@@ -102,12 +102,12 @@ test('Return empty array if lastRelease.gitHead is the last commit', async (t) =
t.deepEqual(result, []);
});
test('Return empty array if there is no commits', async (t) => {
test("Return empty array if there is no commits", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Retrieve the commits with the commits module
const result = await getCommits({cwd, lastRelease: {}, logger: t.context.logger});
const result = await getCommits({ cwd, lastRelease: {}, logger: t.context.logger });
// Verify no commit is retrieved
t.deepEqual(result, []);
+319 -311
View File
@@ -1,589 +1,597 @@
import path from 'node:path';
import {format} from 'node:util';
import test from 'ava';
import fsExtra from 'fs-extra';
import {omit} from 'lodash-es';
import * as td from 'testdouble';
import yaml from 'js-yaml';
import {gitAddConfig, gitCommits, gitRepo, gitShallowClone, gitTagVersion} from './helpers/git-utils.js';
import path from "node:path";
import { format } from "node:util";
import test from "ava";
import fsExtra from "fs-extra";
import { omit } from "lodash-es";
import * as td from "testdouble";
import yaml from "js-yaml";
import { gitAddConfig, gitCommits, gitRepo, gitShallowClone, gitTagVersion } from "./helpers/git-utils.js";
const {outputJson, writeFile} = fsExtra;
const pluginsConfig = {foo: 'bar', baz: 'qux'};
const { outputJson, writeFile } = fsExtra;
const pluginsConfig = { foo: "bar", baz: "qux" };
let plugins;
const DEFAULT_PLUGINS = [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/npm',
'@semantic-release/github',
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github",
];
test.beforeEach(async (t) => {
plugins = (await td.replaceEsm('../lib/plugins/index.js')).default;
t.context.getConfig = (await import('../lib/get-config.js')).default;
plugins = (await td.replaceEsm("../lib/plugins/index.js")).default;
t.context.getConfig = (await import("../lib/get-config.js")).default;
});
test.afterEach.always((t) => {
td.reset();
});
test('Default values, reading repositoryUrl from package.json', async (t) => {
const pkg = {repository: 'https://host.null/owner/package.git'};
test("Default values, reading repositoryUrl from package.json", async (t) => {
const pkg = { repository: "https://host.null/owner/package.git" };
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
await gitTagVersion('v1.1.0', undefined, {cwd});
const { cwd } = await gitRepo(true);
await gitCommits(["First"], { cwd });
await gitTagVersion("v1.0.0", undefined, { cwd });
await gitTagVersion("v1.1.0", undefined, { cwd });
// Add remote.origin.url config
await gitAddConfig('remote.origin.url', 'git@host.null:owner/repo.git', {cwd});
await gitAddConfig("remote.origin.url", "git@host.null:owner/repo.git", { cwd });
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), pkg);
await outputJson(path.resolve(cwd, "package.json"), pkg);
const {options: result} = await t.context.getConfig({cwd});
const { options: result } = await t.context.getConfig({ cwd });
// Verify the default options are set
t.deepEqual(result.branches, [
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
{name: 'beta', prerelease: true},
{name: 'alpha', prerelease: true},
"+([0-9])?(.{+([0-9]),x}).x",
"master",
"next",
"next-major",
{ name: "beta", prerelease: true },
{ name: "alpha", prerelease: true },
]);
t.is(result.repositoryUrl, 'https://host.null/owner/package.git');
t.is(result.repositoryUrl, "https://host.null/owner/package.git");
t.is(result.tagFormat, `v\${version}`);
});
test('Default values, reading repositoryUrl from repo if not set in package.json', async (t) => {
test("Default values, reading repositoryUrl from repo if not set in package.json", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo(true);
const { cwd } = await gitRepo(true);
// Add remote.origin.url config
await gitAddConfig('remote.origin.url', 'https://host.null/owner/module.git', {cwd});
await gitAddConfig("remote.origin.url", "https://host.null/owner/module.git", { cwd });
const {options: result} = await t.context.getConfig({cwd});
const { options: result } = await t.context.getConfig({ cwd });
// Verify the default options are set
t.deepEqual(result.branches, [
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
{name: 'beta', prerelease: true},
{name: 'alpha', prerelease: true},
"+([0-9])?(.{+([0-9]),x}).x",
"master",
"next",
"next-major",
{ name: "beta", prerelease: true },
{ name: "alpha", prerelease: true },
]);
t.is(result.repositoryUrl, 'https://host.null/owner/module.git');
t.is(result.repositoryUrl, "https://host.null/owner/module.git");
t.is(result.tagFormat, `v\${version}`);
});
test('Default values, reading repositoryUrl (http url) from package.json if not set in repo', async (t) => {
const pkg = {repository: 'https://host.null/owner/module.git'};
test("Default values, reading repositoryUrl (http url) from package.json if not set in repo", async (t) => {
const pkg = { repository: "https://host.null/owner/module.git" };
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), pkg);
await outputJson(path.resolve(cwd, "package.json"), pkg);
const {options: result} = await t.context.getConfig({cwd});
const { options: result } = await t.context.getConfig({ cwd });
// Verify the default options are set
t.deepEqual(result.branches, [
'+([0-9])?(.{+([0-9]),x}).x',
'master',
'next',
'next-major',
{name: 'beta', prerelease: true},
{name: 'alpha', prerelease: true},
"+([0-9])?(.{+([0-9]),x}).x",
"master",
"next",
"next-major",
{ name: "beta", prerelease: true },
{ name: "alpha", prerelease: true },
]);
t.is(result.repositoryUrl, 'https://host.null/owner/module.git');
t.is(result.repositoryUrl, "https://host.null/owner/module.git");
t.is(result.tagFormat, `v\${version}`);
});
test('Convert "ci" option to "noCi"', async (t) => {
const pkg = {repository: 'https://host.null/owner/module.git', release: {ci: false}};
const pkg = { repository: "https://host.null/owner/module.git", release: { ci: false } };
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), pkg);
await outputJson(path.resolve(cwd, "package.json"), pkg);
const {options: result} = await t.context.getConfig({cwd});
const { options: result } = await t.context.getConfig({ cwd });
t.is(result.noCi, true);
});
test.serial('Read options from package.json', async (t) => {
test.serial("Read options from package.json", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
generateNotes: 'generateNotes',
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
generateNotes: "generateNotes",
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Verify the plugins module is called with the plugin options from package.json
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: options});
await outputJson(path.resolve(cwd, "package.json"), { release: options });
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from package.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read options from .releaserc.yml', async (t) => {
test.serial("Read options from .releaserc.yml", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json in repository root
await writeFile(path.resolve(cwd, '.releaserc.yml'), yaml.dump(options));
await writeFile(path.resolve(cwd, ".releaserc.yml"), yaml.dump(options));
// Verify the plugins module is called with the plugin options from package.json
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from package.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read options from .releaserc.json', async (t) => {
test.serial("Read options from .releaserc.json", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json in repository root
await outputJson(path.resolve(cwd, '.releaserc.json'), options);
await outputJson(path.resolve(cwd, ".releaserc.json"), options);
// Verify the plugins module is called with the plugin options from package.json
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from package.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read options from .releaserc.js', async (t) => {
test.serial("Read options from .releaserc.js", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json in repository root
await writeFile(path.resolve(cwd, '.releaserc.js'), `module.exports = ${JSON.stringify(options)}`);
await writeFile(path.resolve(cwd, ".releaserc.js"), `module.exports = ${JSON.stringify(options)}`);
// Verify the plugins module is called with the plugin options from package.json
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from package.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read options from .releaserc.cjs', async (t) => {
test.serial("Read options from .releaserc.cjs", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create .releaserc.cjs in repository root
await writeFile(path.resolve(cwd, '.releaserc.cjs'), `module.exports = ${JSON.stringify(options)}`);
await writeFile(path.resolve(cwd, ".releaserc.cjs"), `module.exports = ${JSON.stringify(options)}`);
// Verify the plugins module is called with the plugin options from .releaserc.cjs
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from .releaserc.cjs
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read options from release.config.js', async (t) => {
test.serial("Read options from release.config.js", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json in repository root
await writeFile(path.resolve(cwd, 'release.config.js'), `module.exports = ${JSON.stringify(options)}`);
await writeFile(path.resolve(cwd, "release.config.js"), `module.exports = ${JSON.stringify(options)}`);
// Verify the plugins module is called with the plugin options from package.json
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from package.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read options from release.config.cjs', async (t) => {
test.serial("Read options from release.config.cjs", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Verify the plugins module is called with the plugin options from release.config.cjs
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
// Create release.config.cjs in repository root
await writeFile(path.resolve(cwd, 'release.config.cjs'), `module.exports = ${JSON.stringify(options)}`);
await writeFile(path.resolve(cwd, "release.config.cjs"), `module.exports = ${JSON.stringify(options)}`);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from release.config.cjs
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Prioritise CLI/API parameters over file configuration and git repo', async (t) => {
test.serial("Prioritise CLI/API parameters over file configuration and git repo", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
let { cwd, repositoryUrl } = await gitRepo();
await gitCommits(["First"], { cwd });
// Create a clone
cwd = await gitShallowClone(repositoryUrl);
const pkgOptions = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_pkg'},
branches: ['branch_pkg'],
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_pkg" },
branches: ["branch_pkg"],
};
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_cli'},
branches: ['branch_cli'],
repositoryUrl: 'http://cli-url.com/owner/package',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_cli" },
branches: ["branch_cli"],
repositoryUrl: "http://cli-url.com/owner/package",
tagFormat: `cli\${version}`,
plugins: false,
};
// Verify the plugins module is called with the plugin options from CLI/API
td.when(plugins({cwd, options}, {})).thenResolve(pluginsConfig);
const pkg = {release: pkgOptions, repository: 'git@host.null:owner/module.git'};
td.when(plugins({ cwd, options }, {})).thenResolve(pluginsConfig);
const pkg = { release: pkgOptions, repository: "git@host.null:owner/module.git" };
// Create package.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), pkg);
await outputJson(path.resolve(cwd, "package.json"), pkg);
const result = await t.context.getConfig({cwd}, options);
const result = await t.context.getConfig({ cwd }, options);
// Verify the options contains the plugin config from CLI/API
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read configuration from file path in "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: './shareable.json'};
const { cwd } = await gitRepo();
const pkgOptions = { extends: "./shareable.json" };
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
generateNotes: 'generateNotes',
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
generateNotes: "generateNotes",
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: ['plugin-1', ['plugin-2', {plugin2Opt: 'value'}]],
plugins: ["plugin-1", ["plugin-2", { plugin2Opt: "value" }]],
};
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'shareable.json'), options);
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "shareable.json"), options);
// Verify the plugins module is called with the plugin options from shareable.json
td.when(plugins(
{cwd, options},
{
analyzeCommits: './shareable.json',
generateNotes: './shareable.json',
'plugin-1': './shareable.json',
'plugin-2': './shareable.json',
}
)).thenResolve(pluginsConfig);
td.when(
plugins(
{ cwd, options },
{
analyzeCommits: "./shareable.json",
generateNotes: "./shareable.json",
"plugin-1": "./shareable.json",
"plugin-2": "./shareable.json",
}
)
).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read configuration from module path in "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: 'shareable'};
const { cwd } = await gitRepo();
const pkgOptions = { extends: "shareable" };
const options = {
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
generateNotes: 'generateNotes',
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
generateNotes: "generateNotes",
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'node_modules/shareable/index.json'), options);
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "node_modules/shareable/index.json"), options);
// Verify the plugins module is called with the plugin options from shareable.json
td.when(plugins(
{cwd, options},
{analyzeCommits: 'shareable', generateNotes: 'shareable'}
)).thenResolve(pluginsConfig);
td.when(plugins({ cwd, options }, { analyzeCommits: "shareable", generateNotes: "shareable" })).thenResolve(
pluginsConfig
);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, {options, plugins: pluginsConfig});
t.deepEqual(result, { options, plugins: pluginsConfig });
});
test.serial('Read configuration from an array of paths in "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: ['./shareable1.json', './shareable2.json']};
const { cwd } = await gitRepo();
const pkgOptions = { extends: ["./shareable1.json", "./shareable2.json"] };
const options1 = {
verifyRelease: 'verifyRelease1',
analyzeCommits: {path: 'analyzeCommits1', param: 'analyzeCommits_param1'},
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
verifyRelease: "verifyRelease1",
analyzeCommits: { path: "analyzeCommits1", param: "analyzeCommits_param1" },
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
};
const options2 = {
verifyRelease: 'verifyRelease2',
generateNotes: 'generateNotes2',
analyzeCommits: {path: 'analyzeCommits2', param: 'analyzeCommits_param2'},
branches: ['test_branch'],
verifyRelease: "verifyRelease2",
generateNotes: "generateNotes2",
analyzeCommits: { path: "analyzeCommits2", param: "analyzeCommits_param2" },
branches: ["test_branch"],
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
await outputJson(path.resolve(cwd, 'shareable2.json'), options2);
const expectedOptions = {...options1, ...options2, branches: ['test_branch']};
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "shareable1.json"), options1);
await outputJson(path.resolve(cwd, "shareable2.json"), options2);
const expectedOptions = { ...options1, ...options2, branches: ["test_branch"] };
// Verify the plugins module is called with the plugin options from shareable1.json and shareable2.json
td.when(plugins(
{options: expectedOptions, cwd},
{
verifyRelease1: './shareable1.json',
verifyRelease2: './shareable2.json',
generateNotes2: './shareable2.json',
analyzeCommits1: './shareable1.json',
analyzeCommits2: './shareable2.json',
}
)).thenResolve(pluginsConfig);
td.when(
plugins(
{ options: expectedOptions, cwd },
{
verifyRelease1: "./shareable1.json",
verifyRelease2: "./shareable2.json",
generateNotes2: "./shareable2.json",
analyzeCommits1: "./shareable1.json",
analyzeCommits2: "./shareable2.json",
}
)
).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from shareable1.json and shareable2.json
t.deepEqual(result, {options: expectedOptions, plugins: pluginsConfig});
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
});
test.serial('Prioritize configuration from config file over "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const pkgOptions = {
extends: './shareable.json',
branches: ['test_pkg'],
generateNotes: 'generateNotes',
publish: [{path: 'publishPkg', param: 'publishPkg_param'}],
extends: "./shareable.json",
branches: ["test_pkg"],
generateNotes: "generateNotes",
publish: [{ path: "publishPkg", param: "publishPkg_param" }],
};
const options1 = {
analyzeCommits: 'analyzeCommits',
generateNotes: 'generateNotesShareable',
publish: [{path: 'publishShareable', param: 'publishShareable_param'}],
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: "analyzeCommits",
generateNotes: "generateNotesShareable",
publish: [{ path: "publishShareable", param: "publishShareable_param" }],
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'shareable.json'), options1);
const expectedOptions = omit({...options1, ...pkgOptions, branches: ['test_pkg']}, 'extends');
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "shareable.json"), options1);
const expectedOptions = omit({ ...options1, ...pkgOptions, branches: ["test_pkg"] }, "extends");
// Verify the plugins module is called with the plugin options from package.json and shareable.json
td.when(plugins(
{cwd, options: expectedOptions},
{
analyzeCommits: './shareable.json',
generateNotesShareable: './shareable.json',
publishShareable: './shareable.json',
}
)).thenResolve(pluginsConfig);
td.when(
plugins(
{ cwd, options: expectedOptions },
{
analyzeCommits: "./shareable.json",
generateNotesShareable: "./shareable.json",
publishShareable: "./shareable.json",
}
)
).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from package.json and shareable.json
t.deepEqual(result, {options: expectedOptions, plugins: pluginsConfig});
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
});
test.serial('Prioritize configuration from cli/API options over "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const cliOptions = {
extends: './shareable2.json',
branches: ['branch_opts'],
publish: [{path: 'publishOpts', param: 'publishOpts_param'}],
repositoryUrl: 'https://host.null/owner/module.git',
extends: "./shareable2.json",
branches: ["branch_opts"],
publish: [{ path: "publishOpts", param: "publishOpts_param" }],
repositoryUrl: "https://host.null/owner/module.git",
};
const pkgOptions = {
extends: './shareable1.json',
branches: ['branch_pkg'],
generateNotes: 'generateNotes',
publish: [{path: 'publishPkg', param: 'publishPkg_param'}],
extends: "./shareable1.json",
branches: ["branch_pkg"],
generateNotes: "generateNotes",
publish: [{ path: "publishPkg", param: "publishPkg_param" }],
};
const options1 = {
analyzeCommits: 'analyzeCommits1',
generateNotes: 'generateNotesShareable1',
publish: [{path: 'publishShareable', param: 'publishShareable_param1'}],
branches: ['test_branch1'],
repositoryUrl: 'https://host.null/owner/module.git',
analyzeCommits: "analyzeCommits1",
generateNotes: "generateNotesShareable1",
publish: [{ path: "publishShareable", param: "publishShareable_param1" }],
branches: ["test_branch1"],
repositoryUrl: "https://host.null/owner/module.git",
};
const options2 = {
analyzeCommits: 'analyzeCommits2',
publish: [{path: 'publishShareable', param: 'publishShareable_param2'}],
branches: ['test_branch2'],
analyzeCommits: "analyzeCommits2",
publish: [{ path: "publishShareable", param: "publishShareable_param2" }],
branches: ["test_branch2"],
tagFormat: `v\${version}`,
plugins: false,
};
// Create package.json, shareable1.json and shareable2.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
await outputJson(path.resolve(cwd, 'shareable2.json'), options2);
const expectedOptions = omit({...options2, ...pkgOptions, ...cliOptions, branches: ['branch_opts']}, 'extends');
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "shareable1.json"), options1);
await outputJson(path.resolve(cwd, "shareable2.json"), options2);
const expectedOptions = omit({ ...options2, ...pkgOptions, ...cliOptions, branches: ["branch_opts"] }, "extends");
// Verify the plugins module is called with the plugin options from package.json and shareable2.json
td.when(plugins(
{cwd, options: expectedOptions},
{analyzeCommits2: './shareable2.json', publishShareable: './shareable2.json'}
)).thenResolve(pluginsConfig);
td.when(
plugins(
{ cwd, options: expectedOptions },
{ analyzeCommits2: "./shareable2.json", publishShareable: "./shareable2.json" }
)
).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd}, cliOptions);
const result = await t.context.getConfig({ cwd }, cliOptions);
// Verify the options contains the plugin config from package.json and shareable2.json
t.deepEqual(result, {options: expectedOptions, plugins: pluginsConfig});
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
});
test.serial('Allow to unset properties defined in shareable config with "null"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const pkgOptions = {
extends: './shareable.json',
extends: "./shareable.json",
analyzeCommits: null,
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
plugins: null,
};
const options1 = {
generateNotes: 'generateNotes',
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
generateNotes: "generateNotes",
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
tagFormat: `v\${version}`,
plugins: ['test-plugin'],
plugins: ["test-plugin"],
};
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'shareable.json'), options1);
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "shareable.json"), options1);
// Verify the plugins module is called with the plugin options from shareable.json and the default `plugins`
td.when(plugins(
{
options: {
...omit(options1, 'analyzeCommits'),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
plugins: DEFAULT_PLUGINS,
td.when(
plugins(
{
options: {
...omit(options1, "analyzeCommits"),
...omit(pkgOptions, ["extends", "analyzeCommits"]),
plugins: DEFAULT_PLUGINS,
},
cwd,
},
cwd,
},
{
generateNotes: './shareable.json',
analyzeCommits: './shareable.json',
'test-plugin': './shareable.json',
}
)).thenResolve(pluginsConfig);
{
generateNotes: "./shareable.json",
analyzeCommits: "./shareable.json",
"test-plugin": "./shareable.json",
}
)
).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from shareable.json and the default `plugins`
t.deepEqual(
result,
{
options: {
...omit(options1, ['analyzeCommits']),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
plugins: DEFAULT_PLUGINS,
},
plugins: pluginsConfig
}
);
t.deepEqual(result, {
options: {
...omit(options1, ["analyzeCommits"]),
...omit(pkgOptions, ["extends", "analyzeCommits"]),
plugins: DEFAULT_PLUGINS,
},
plugins: pluginsConfig,
});
});
test.serial('Allow to unset properties defined in shareable config with "undefined"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
const pkgOptions = {
extends: './shareable.json',
extends: "./shareable.json",
analyzeCommits: undefined,
branches: ['test_branch'],
repositoryUrl: 'https://host.null/owner/module.git',
branches: ["test_branch"],
repositoryUrl: "https://host.null/owner/module.git",
};
const options1 = {
generateNotes: 'generateNotes',
analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'},
generateNotes: "generateNotes",
analyzeCommits: { path: "analyzeCommits", param: "analyzeCommits_param" },
tagFormat: `v\${version}`,
plugins: false,
};
// Create release.config.js and shareable.json in repository root
await writeFile(path.resolve(cwd, 'release.config.js'), `module.exports = ${format(pkgOptions)}`);
await outputJson(path.resolve(cwd, 'shareable.json'), options1);
await writeFile(path.resolve(cwd, "release.config.js"), `module.exports = ${format(pkgOptions)}`);
await outputJson(path.resolve(cwd, "shareable.json"), options1);
const expectedOptions = {
...omit(options1, 'analyzeCommits'),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
branches: ['test_branch'],
...omit(options1, "analyzeCommits"),
...omit(pkgOptions, ["extends", "analyzeCommits"]),
branches: ["test_branch"],
};
// Verify the plugins module is called with the plugin options from shareable.json
td.when(plugins(
{options: expectedOptions, cwd},
{generateNotes: './shareable.json', analyzeCommits: './shareable.json'}
)).thenResolve(pluginsConfig);
td.when(
plugins(
{ options: expectedOptions, cwd },
{ generateNotes: "./shareable.json", analyzeCommits: "./shareable.json" }
)
).thenResolve(pluginsConfig);
const result = await t.context.getConfig({cwd});
const result = await t.context.getConfig({ cwd });
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, {options: expectedOptions, plugins: pluginsConfig});
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
});
test('Throw an Error if one of the shareable config cannot be found', async (t) => {
test("Throw an Error if one of the shareable config cannot be found", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: ['./shareable1.json', 'non-existing-path']};
const options1 = {analyzeCommits: 'analyzeCommits'};
const { cwd } = await gitRepo();
const pkgOptions = { extends: ["./shareable1.json", "non-existing-path"] };
const options1 = { analyzeCommits: "analyzeCommits" };
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'shareable1.json'), options1);
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "shareable1.json"), options1);
await t.throwsAsync(t.context.getConfig({cwd}), {
await t.throwsAsync(t.context.getConfig({ cwd }), {
message: /Cannot find module 'non-existing-path'/,
code: 'MODULE_NOT_FOUND',
code: "MODULE_NOT_FOUND",
});
});
test('Convert "ci" option to "noCi" when set from extended config', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: './no-ci.json'};
const { cwd } = await gitRepo();
const pkgOptions = { extends: "./no-ci.json" };
const options = {
ci: false,
};
// Create package.json and shareable.json in repository root
await outputJson(path.resolve(cwd, 'package.json'), {release: pkgOptions});
await outputJson(path.resolve(cwd, 'no-ci.json'), options);
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
await outputJson(path.resolve(cwd, "no-ci.json"), options);
const {options: result} = await t.context.getConfig({cwd});
const { options: result } = await t.context.getConfig({ cwd });
t.is(result.ci, false);
t.is(result.noCi, true);
+145 -140
View File
@@ -1,408 +1,413 @@
import test from 'ava';
import getAuthUrl from '../lib/get-git-auth-url.js';
import {gitRepo} from './helpers/git-utils.js';
import test from "ava";
import getAuthUrl from "../lib/get-git-auth-url.js";
import { gitRepo } from "./helpers/git-utils.js";
const env = {GIT_ASKPASS: 'echo', GIT_TERMINAL_PROMPT: 0};
const env = { GIT_ASKPASS: "echo", GIT_TERMINAL_PROMPT: 0 };
test('Return the same "git" formatted URL if "gitCredentials" is not defined', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({cwd, env, branch: {name: 'master'}, options: {repositoryUrl: 'git@host.null:owner/repo.git'}}),
'git@host.null:owner/repo.git'
await getAuthUrl({
cwd,
env,
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
"git@host.null:owner/repo.git"
);
});
test('Return the same "https" formatted URL if "gitCredentials" is not defined', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env,
branch: {name: 'master'},
options: {repositoryUrl: 'https://host.null/owner/repo.git'},
branch: { name: "master" },
options: { repositoryUrl: "https://host.null/owner/repo.git" },
}),
'https://host.null/owner/repo.git'
"https://host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is not defined and repositoryUrl is a "git+https" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env,
branch: {name: 'master'},
options: {repositoryUrl: 'git+https://host.null/owner/repo.git'},
branch: { name: "master" },
options: { repositoryUrl: "git+https://host.null/owner/repo.git" },
}),
'https://host.null/owner/repo.git'
"https://host.null/owner/repo.git"
);
});
test('Do not add trailing ".git" if not present in the origian URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({cwd, env, vranch: {name: 'master'}, options: {repositoryUrl: 'git@host.null:owner/repo'}}),
'git@host.null:owner/repo'
await getAuthUrl({ cwd, env, vranch: { name: "master" }, options: { repositoryUrl: "git@host.null:owner/repo" } }),
"git@host.null:owner/repo"
);
});
test('Handle "https" URL with group and subgroup', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env,
branch: {name: 'master'},
options: {repositoryUrl: 'https://host.null/group/subgroup/owner/repo.git'},
branch: { name: "master" },
options: { repositoryUrl: "https://host.null/group/subgroup/owner/repo.git" },
}),
'https://host.null/group/subgroup/owner/repo.git'
"https://host.null/group/subgroup/owner/repo.git"
);
});
test('Handle "git" URL with group and subgroup', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env,
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:group/subgroup/owner/repo.git'},
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:group/subgroup/owner/repo.git" },
}),
'git@host.null:group/subgroup/owner/repo.git'
"git@host.null:group/subgroup/owner/repo.git"
);
});
test('Convert shorthand URL', async (t) => {
const {cwd} = await gitRepo();
test("Convert shorthand URL", async (t) => {
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env,
branch: {name: 'master'},
options: {repositoryUrl: 'semantic-release/semantic-release'},
branch: { name: "master" },
options: { repositoryUrl: "semantic-release/semantic-release" },
}),
'https://github.com/semantic-release/semantic-release.git'
"https://github.com/semantic-release/semantic-release.git"
);
});
test('Convert GitLab shorthand URL', async (t) => {
const {cwd} = await gitRepo();
test("Convert GitLab shorthand URL", async (t) => {
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env,
branch: {name: 'master'},
options: {repositoryUrl: 'gitlab:semantic-release/semantic-release'},
branch: { name: "master" },
options: { repositoryUrl: "gitlab:semantic-release/semantic-release" },
}),
'https://gitlab.com/semantic-release/semantic-release.git'
"https://gitlab.com/semantic-release/semantic-release.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://user:pass@host.null/owner/repo.git'
"https://user:pass@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
options: {branch: 'master', repositoryUrl: 'host.null:owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
options: { branch: "master", repositoryUrl: "host.null:owner/repo.git" },
}),
'https://user:pass@host.null/owner/repo.git'
"https://user:pass@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user and with a custom port', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
options: {branch: 'master', repositoryUrl: 'host.null:6666:owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
options: { branch: "master", repositoryUrl: "host.null:6666:owner/repo.git" },
}),
'https://user:pass@host.null:6666/owner/repo.git'
"https://user:pass@host.null:6666/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user and with a custom port followed by a slash', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
options: {branch: 'master', repositoryUrl: 'host.null:6666:/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
options: { branch: "master", repositoryUrl: "host.null:6666:/owner/repo.git" },
}),
'https://user:pass@host.null:6666/owner/repo.git'
"https://user:pass@host.null:6666/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "https" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'https://host.null/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "https://host.null/owner/repo.git" },
}),
'https://user:pass@host.null/owner/repo.git'
"https://user:pass@host.null/owner/repo.git"
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'http://host.null/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "http://host.null/owner/repo.git" },
}),
'http://user:pass@host.null/owner/repo.git'
"http://user:pass@host.null/owner/repo.git"
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL with custom port', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
options: {branch: 'master', repositoryUrl: 'http://host.null:8080/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
options: { branch: "master", repositoryUrl: "http://host.null:8080/owner/repo.git" },
}),
'http://user:pass@host.null:8080/owner/repo.git'
"http://user:pass@host.null:8080/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+https" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'git+https://host.null/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "git+https://host.null/owner/repo.git" },
}),
'https://user:pass@host.null/owner/repo.git'
"https://user:pass@host.null/owner/repo.git"
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+http" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'git+http://host.null/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "git+http://host.null/owner/repo.git" },
}),
'http://user:pass@host.null/owner/repo.git'
"http://user:pass@host.null/owner/repo.git"
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "ssh" URL', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
options: {branch: 'master', repositoryUrl: 'ssh://git@host.null:2222/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
options: { branch: "master", repositoryUrl: "ssh://git@host.null:2222/owner/repo.git" },
}),
'https://user:pass@host.null/owner/repo.git'
"https://user:pass@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GH_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GH_TOKEN: 'token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, GH_TOKEN: "token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://token@host.null/owner/repo.git'
"https://token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GITHUB_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GITHUB_TOKEN: 'token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, GITHUB_TOKEN: "token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://token@host.null/owner/repo.git'
"https://token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GL_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GL_TOKEN: 'token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, GL_TOKEN: "token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://gitlab-ci-token:token@host.null/owner/repo.git'
"https://gitlab-ci-token:token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GITLAB_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GITLAB_TOKEN: 'token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, GITLAB_TOKEN: "token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://gitlab-ci-token:token@host.null/owner/repo.git'
"https://gitlab-ci-token:token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "BB_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, BB_TOKEN: 'token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, BB_TOKEN: "token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://x-token-auth:token@host.null/owner/repo.git'
"https://x-token-auth:token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "BITBUCKET_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, BITBUCKET_TOKEN: 'token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, BITBUCKET_TOKEN: "token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://x-token-auth:token@host.null/owner/repo.git'
"https://x-token-auth:token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "BB_TOKEN_BASIC_AUTH"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, BB_TOKEN_BASIC_AUTH: 'username:token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, BB_TOKEN_BASIC_AUTH: "username:token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://username:token@host.null/owner/repo.git'
"https://username:token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "BITBUCKET_TOKEN_BASIC_AUTH"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, BITBUCKET_TOKEN_BASIC_AUTH: 'username:token'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, BITBUCKET_TOKEN_BASIC_AUTH: "username:token" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://username:token@host.null/owner/repo.git'
"https://username:token@host.null/owner/repo.git"
);
});
test('Return the "https" formatted URL if "GITHUB_ACTION" is set', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GITHUB_ACTION: 'foo', GITHUB_TOKEN: 'token'},
options: {branch: 'master', repositoryUrl: 'git@host.null:owner/repo.git'},
env: { ...env, GITHUB_ACTION: "foo", GITHUB_TOKEN: "token" },
options: { branch: "master", repositoryUrl: "git@host.null:owner/repo.git" },
}),
'https://x-access-token:token@host.null/owner/repo.git'
"https://x-access-token:token@host.null/owner/repo.git"
);
});
test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'https://host.null/group/subgroup/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "https://host.null/group/subgroup/owner/repo.git" },
}),
'https://user:pass@host.null/group/subgroup/owner/repo.git'
"https://user:pass@host.null/group/subgroup/owner/repo.git"
);
});
test('Handle "git" URL with group and subgroup, with "GIT_CREDENTIALS', async (t) => {
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl: 'git@host.null:group/subgroup/owner/repo.git'},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl: "git@host.null:group/subgroup/owner/repo.git" },
}),
'https://user:pass@host.null/group/subgroup/owner/repo.git'
"https://user:pass@host.null/group/subgroup/owner/repo.git"
);
});
test('Do not add git credential to repositoryUrl if push is allowed', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
test("Do not add git credential to repositoryUrl if push is allowed", async (t) => {
const { cwd, repositoryUrl } = await gitRepo(true);
t.is(
await getAuthUrl({
cwd,
env: {...env, GIT_CREDENTIALS: 'user:pass'},
branch: {name: 'master'},
options: {repositoryUrl},
env: { ...env, GIT_CREDENTIALS: "user:pass" },
branch: { name: "master" },
options: { repositoryUrl },
}),
repositoryUrl
);
+40 -40
View File
@@ -1,80 +1,80 @@
import test from 'ava';
import getLastRelease from '../lib/get-last-release.js';
import test from "ava";
import getLastRelease from "../lib/get-last-release.js";
test('Get the highest non-prerelease valid tag', (t) => {
test("Get the highest non-prerelease valid tag", (t) => {
const result = getLastRelease({
branch: {
name: 'master',
name: "master",
tags: [
{version: '2.0.0', gitTag: 'v2.0.0', gitHead: 'v2.0.0'},
{version: '1.0.0', gitTag: 'v1.0.0', gitHead: 'v1.0.0'},
{version: '3.0.0-beta.1', gitTag: 'v3.0.0-beta.1', gitHead: 'v3.0.0-beta.1'},
{ version: "2.0.0", gitTag: "v2.0.0", gitHead: "v2.0.0" },
{ version: "1.0.0", gitTag: "v1.0.0", gitHead: "v1.0.0" },
{ version: "3.0.0-beta.1", gitTag: "v3.0.0-beta.1", gitHead: "v3.0.0-beta.1" },
],
type: 'release',
type: "release",
},
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {version: '2.0.0', gitTag: 'v2.0.0', name: 'v2.0.0', gitHead: 'v2.0.0', channels: undefined});
t.deepEqual(result, { version: "2.0.0", gitTag: "v2.0.0", name: "v2.0.0", gitHead: "v2.0.0", channels: undefined });
});
test('Get the highest prerelease valid tag, ignoring other tags from other prerelease channels', (t) => {
test("Get the highest prerelease valid tag, ignoring other tags from other prerelease channels", (t) => {
const result = getLastRelease({
branch: {
name: 'beta',
prerelease: 'beta',
channel: 'beta',
name: "beta",
prerelease: "beta",
channel: "beta",
tags: [
{version: '1.0.0-beta.1', gitTag: 'v1.0.0-beta.1', gitHead: 'v1.0.0-beta.1', channels: ['beta']},
{version: '1.0.0-beta.2', gitTag: 'v1.0.0-beta.2', gitHead: 'v1.0.0-beta.2', channels: ['beta']},
{version: '1.0.0-alpha.1', gitTag: 'v1.0.0-alpha.1', gitHead: 'v1.0.0-alpha.1', channels: ['alpha']},
{ version: "1.0.0-beta.1", gitTag: "v1.0.0-beta.1", gitHead: "v1.0.0-beta.1", channels: ["beta"] },
{ version: "1.0.0-beta.2", gitTag: "v1.0.0-beta.2", gitHead: "v1.0.0-beta.2", channels: ["beta"] },
{ version: "1.0.0-alpha.1", gitTag: "v1.0.0-alpha.1", gitHead: "v1.0.0-alpha.1", channels: ["alpha"] },
],
type: 'prerelease',
type: "prerelease",
},
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {
version: '1.0.0-beta.2',
gitTag: 'v1.0.0-beta.2',
name: 'v1.0.0-beta.2',
gitHead: 'v1.0.0-beta.2',
channels: ['beta'],
version: "1.0.0-beta.2",
gitTag: "v1.0.0-beta.2",
name: "v1.0.0-beta.2",
gitHead: "v1.0.0-beta.2",
channels: ["beta"],
});
});
test('Return empty object if no valid tag is found', (t) => {
test("Return empty object if no valid tag is found", (t) => {
const result = getLastRelease({
branch: {
name: 'master',
tags: [{version: '3.0.0-beta.1', gitTag: 'v3.0.0-beta.1', gitHead: 'v3.0.0-beta.1'}],
type: 'release',
name: "master",
tags: [{ version: "3.0.0-beta.1", gitTag: "v3.0.0-beta.1", gitHead: "v3.0.0-beta.1" }],
type: "release",
},
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {});
});
test('Get the highest non-prerelease valid tag before a certain version', (t) => {
test("Get the highest non-prerelease valid tag before a certain version", (t) => {
const result = getLastRelease(
{
branch: {
name: 'master',
name: "master",
channel: undefined,
tags: [
{version: '2.0.0', gitTag: 'v2.0.0', gitHead: 'v2.0.0'},
{version: '1.0.0', gitTag: 'v1.0.0', gitHead: 'v1.0.0'},
{version: '2.0.0-beta.1', gitTag: 'v2.0.0-beta.1', gitHead: 'v2.0.0-beta.1'},
{version: '2.1.0', gitTag: 'v2.1.0', gitHead: 'v2.1.0'},
{version: '2.1.1', gitTag: 'v2.1.1', gitHead: 'v2.1.1'},
{ version: "2.0.0", gitTag: "v2.0.0", gitHead: "v2.0.0" },
{ version: "1.0.0", gitTag: "v1.0.0", gitHead: "v1.0.0" },
{ version: "2.0.0-beta.1", gitTag: "v2.0.0-beta.1", gitHead: "v2.0.0-beta.1" },
{ version: "2.1.0", gitTag: "v2.1.0", gitHead: "v2.1.0" },
{ version: "2.1.1", gitTag: "v2.1.1", gitHead: "v2.1.1" },
],
type: 'release',
type: "release",
},
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
},
{before: '2.1.0'}
{ before: "2.1.0" }
);
t.deepEqual(result, {version: '2.0.0', gitTag: 'v2.0.0', name: 'v2.0.0', gitHead: 'v2.0.0', channels: undefined});
t.deepEqual(result, { version: "2.0.0", gitTag: "v2.0.0", name: "v2.0.0", gitHead: "v2.0.0", channels: undefined });
});
+7 -7
View File
@@ -1,15 +1,15 @@
import test from 'ava';
import {spy} from 'sinon';
import getLogger from '../lib/get-logger.js';
import test from "ava";
import { spy } from "sinon";
import getLogger from "../lib/get-logger.js";
test('Expose "error", "success" and "log" functions', (t) => {
const stdout = spy();
const stderr = spy();
const logger = getLogger({stdout: {write: stdout}, stderr: {write: stderr}});
const logger = getLogger({ stdout: { write: stdout }, stderr: { write: stderr } });
logger.log('test log');
logger.success('test success');
logger.error('test error');
logger.log("test log");
logger.success("test success");
logger.error("test error");
t.regex(stdout.args[0][0], /.*test log/);
t.regex(stdout.args[1][0], /.*test success/);
+123 -123
View File
@@ -1,277 +1,277 @@
import test from 'ava';
import {stub} from 'sinon';
import getNextVersion from '../lib/get-next-version.js';
import test from "ava";
import { stub } from "sinon";
import getNextVersion from "../lib/get-next-version.js";
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = stub();
t.context.logger = {log: t.context.log};
t.context.logger = { log: t.context.log };
});
test('Increase version for patch release', (t) => {
test("Increase version for patch release", (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}]},
nextRelease: {type: 'patch'},
lastRelease: {version: '1.0.0', channels: [null]},
branch: { name: "master", type: "release", tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }] },
nextRelease: { type: "patch" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
}),
'1.0.1'
"1.0.1"
);
});
test('Increase version for minor release', (t) => {
test("Increase version for minor release", (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}]},
nextRelease: {type: 'minor'},
lastRelease: {version: '1.0.0', channels: [null]},
branch: { name: "master", type: "release", tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }] },
nextRelease: { type: "minor" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
}),
'1.1.0'
"1.1.0"
);
});
test('Increase version for major release', (t) => {
test("Increase version for major release", (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}]},
nextRelease: {type: 'major'},
lastRelease: {version: '1.0.0', channels: [null]},
branch: { name: "master", type: "release", tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }] },
nextRelease: { type: "major" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
}),
'2.0.0'
"2.0.0"
);
});
test('Return 1.0.0 if there is no previous release', (t) => {
test("Return 1.0.0 if there is no previous release", (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: []},
nextRelease: {type: 'minor'},
branch: { name: "master", type: "release", tags: [] },
nextRelease: { type: "minor" },
lastRelease: {},
logger: t.context.logger,
}),
'1.0.0'
"1.0.0"
);
});
test('Increase version for patch release on prerelease branch', (t) => {
test("Increase version for patch release on prerelease branch", (t) => {
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}],
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }],
},
nextRelease: {type: 'patch', channel: 'beta'},
lastRelease: {version: '1.0.0', channels: [null]},
nextRelease: { type: "patch", channel: "beta" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
}),
'1.0.1-beta.1'
"1.0.1-beta.1"
);
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.0.1-beta.1', version: '1.0.1-beta.1', channels: ['beta']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.0.1-beta.1", version: "1.0.1-beta.1", channels: ["beta"] },
],
},
nextRelease: {type: 'patch', channel: 'beta'},
lastRelease: {version: '1.0.1-beta.1', channels: ['beta']},
nextRelease: { type: "patch", channel: "beta" },
lastRelease: { version: "1.0.1-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'1.0.1-beta.2'
"1.0.1-beta.2"
);
t.is(
getNextVersion({
branch: {
name: 'alpha',
type: 'prerelease',
prerelease: 'alpha',
tags: [{gitTag: 'v1.0.1-beta.1', version: '1.0.1-beta.1', channels: ['beta']}],
name: "alpha",
type: "prerelease",
prerelease: "alpha",
tags: [{ gitTag: "v1.0.1-beta.1", version: "1.0.1-beta.1", channels: ["beta"] }],
},
nextRelease: {type: 'patch', channel: 'alpha'},
lastRelease: {version: '1.0.1-beta.1', channels: ['beta']},
nextRelease: { type: "patch", channel: "alpha" },
lastRelease: { version: "1.0.1-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'1.0.2-alpha.1'
"1.0.2-alpha.1"
);
});
test('Increase version for minor release on prerelease branch', (t) => {
test("Increase version for minor release on prerelease branch", (t) => {
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}],
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }],
},
nextRelease: {type: 'minor', channel: 'beta'},
lastRelease: {version: '1.0.0', channels: [null]},
nextRelease: { type: "minor", channel: "beta" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
}),
'1.1.0-beta.1'
"1.1.0-beta.1"
);
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0-beta.1', version: '1.1.0-beta.1', channels: ['beta']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: ["beta"] },
],
},
nextRelease: {type: 'minor', channel: 'beta'},
lastRelease: {version: '1.1.0-beta.1', channels: ['beta']},
nextRelease: { type: "minor", channel: "beta" },
lastRelease: { version: "1.1.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'1.1.0-beta.2'
"1.1.0-beta.2"
);
t.is(
getNextVersion({
branch: {
name: 'alpha',
type: 'prerelease',
prerelease: 'alpha',
tags: [{gitTag: 'v1.1.0-beta.1', version: '1.1.0-beta.1', channels: ['beta']}],
name: "alpha",
type: "prerelease",
prerelease: "alpha",
tags: [{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: ["beta"] }],
},
nextRelease: {type: 'minor', channel: 'alpha'},
lastRelease: {version: '1.1.0-beta.1', channels: ['beta']},
nextRelease: { type: "minor", channel: "alpha" },
lastRelease: { version: "1.1.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'1.2.0-alpha.1'
"1.2.0-alpha.1"
);
});
test('Increase version for major release on prerelease branch', (t) => {
test("Increase version for major release on prerelease branch", (t) => {
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}],
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] }],
},
nextRelease: {type: 'major', channel: 'beta'},
lastRelease: {version: '1.0.0', channels: [null]},
nextRelease: { type: "major", channel: "beta" },
lastRelease: { version: "1.0.0", channels: [null] },
logger: t.context.logger,
}),
'2.0.0-beta.1'
"2.0.0-beta.1"
);
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v2.0.0-beta.1', version: '2.0.0-beta.1', channels: ['beta']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v2.0.0-beta.1", version: "2.0.0-beta.1", channels: ["beta"] },
],
},
nextRelease: {type: 'major', channel: 'beta'},
lastRelease: {version: '2.0.0-beta.1', channels: ['beta']},
nextRelease: { type: "major", channel: "beta" },
lastRelease: { version: "2.0.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'2.0.0-beta.2'
"2.0.0-beta.2"
);
t.is(
getNextVersion({
branch: {
name: 'alpha',
type: 'prerelease',
prerelease: 'alpha',
tags: [{gitTag: 'v2.0.0-beta.1', version: '2.0.0-beta.1', channels: ['beta']}],
name: "alpha",
type: "prerelease",
prerelease: "alpha",
tags: [{ gitTag: "v2.0.0-beta.1", version: "2.0.0-beta.1", channels: ["beta"] }],
},
nextRelease: {type: 'major', channel: 'alpha'},
lastRelease: {version: '2.0.0-beta.1', channels: ['beta']},
nextRelease: { type: "major", channel: "alpha" },
lastRelease: { version: "2.0.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'3.0.0-alpha.1'
"3.0.0-alpha.1"
);
});
test('Return 1.0.0 if there is no previous release on prerelease branch', (t) => {
test("Return 1.0.0 if there is no previous release on prerelease branch", (t) => {
t.is(
getNextVersion({
branch: {name: 'beta', type: 'prerelease', prerelease: 'beta', tags: []},
nextRelease: {type: 'minor'},
branch: { name: "beta", type: "prerelease", prerelease: "beta", tags: [] },
nextRelease: { type: "minor" },
lastRelease: {},
logger: t.context.logger,
}),
'1.0.0-beta.1'
"1.0.0-beta.1"
);
});
test('Increase version for release on prerelease branch after previous commits were merged to release branch', (t) => {
test("Increase version for release on prerelease branch after previous commits were merged to release branch", (t) => {
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0', version: '1.1.0', channels: [null]}, // Version v1.1.0 released on default branch after beta was merged into master
{gitTag: 'v1.1.0-beta.1', version: '1.1.0-beta.1', channels: [null, 'beta']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: [null] }, // Version v1.1.0 released on default branch after beta was merged into master
{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: [null, "beta"] },
],
},
nextRelease: {type: 'minor'},
lastRelease: {version: '1.1.0', channels: [null]},
nextRelease: { type: "minor" },
lastRelease: { version: "1.1.0", channels: [null] },
logger: t.context.logger,
}),
'1.2.0-beta.1'
"1.2.0-beta.1"
);
});
test('Increase version for release on prerelease branch based on highest commit type since last regular release', (t) => {
test("Increase version for release on prerelease branch based on highest commit type since last regular release", (t) => {
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0-beta.1', version: '1.1.0-beta.1', channels: [null, 'beta']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0-beta.1", version: "1.1.0-beta.1", channels: [null, "beta"] },
],
},
nextRelease: {type: 'major'},
lastRelease: {version: 'v1.1.0-beta.1', channels: [null]},
nextRelease: { type: "major" },
lastRelease: { version: "v1.1.0-beta.1", channels: [null] },
logger: t.context.logger,
}),
'2.0.0-beta.1'
"2.0.0-beta.1"
);
});
test('Increase version for release on prerelease branch when there is no regular releases on other branches', (t) => {
test("Increase version for release on prerelease branch when there is no regular releases on other branches", (t) => {
t.is(
getNextVersion({
branch: {
name: 'beta',
type: 'prerelease',
prerelease: 'beta',
tags: [{gitTag: 'v1.0.0-beta.1', version: '1.0.0-beta.1', channels: ['beta']}],
name: "beta",
type: "prerelease",
prerelease: "beta",
tags: [{ gitTag: "v1.0.0-beta.1", version: "1.0.0-beta.1", channels: ["beta"] }],
},
nextRelease: {type: 'minor', channel: 'beta'},
lastRelease: {version: 'v1.0.0-beta.1', channels: ['beta']},
nextRelease: { type: "minor", channel: "beta" },
lastRelease: { version: "v1.0.0-beta.1", channels: ["beta"] },
logger: t.context.logger,
}),
'1.0.0-beta.2'
"1.0.0-beta.2"
);
});
+149 -149
View File
@@ -1,189 +1,189 @@
import test from 'ava';
import getReleaseToAdd from '../lib/get-release-to-add.js';
import test from "ava";
import getReleaseToAdd from "../lib/get-release-to-add.js";
test('Return versions merged from release to maintenance branch, excluding lower than branch start range', (t) => {
test("Return versions merged from release to maintenance branch, excluding lower than branch start range", (t) => {
const result = getReleaseToAdd({
branch: {
name: '2.x',
channel: '2.x',
type: 'maintenance',
mergeRange: '>=2.0.0 <3.0.0',
name: "2.x",
channel: "2.x",
type: "maintenance",
mergeRange: ">=2.0.0 <3.0.0",
tags: [
{gitTag: 'v2.0.0', version: '2.0.0', channels: ['2.x']},
{gitTag: 'v2.0.0', version: '2.0.0', channels: [null]},
{gitTag: 'v2.1.0', version: '2.1.0', channels: [null]},
{gitTag: 'v2.1.1', version: '2.1.1', channels: [null]},
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0', version: '1.1.0', channels: [null]},
{ gitTag: "v2.0.0", version: "2.0.0", channels: ["2.x"] },
{ gitTag: "v2.0.0", version: "2.0.0", channels: [null] },
{ gitTag: "v2.1.0", version: "2.1.0", channels: [null] },
{ gitTag: "v2.1.1", version: "2.1.1", channels: [null] },
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: [null] },
],
},
branches: [{name: '2.x', channel: '2.x'}, {name: 'master'}],
options: {tagFormat: `v\${version}`},
branches: [{ name: "2.x", channel: "2.x" }, { name: "master" }],
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {
lastRelease: {version: '2.1.0', channels: [null], gitTag: 'v2.1.0', name: 'v2.1.0', gitHead: 'v2.1.0'},
lastRelease: { version: "2.1.0", channels: [null], gitTag: "v2.1.0", name: "v2.1.0", gitHead: "v2.1.0" },
currentRelease: {
type: 'patch',
version: '2.1.1',
type: "patch",
version: "2.1.1",
channels: [null],
gitTag: 'v2.1.1',
name: 'v2.1.1',
gitHead: 'v2.1.1',
gitTag: "v2.1.1",
name: "v2.1.1",
gitHead: "v2.1.1",
},
nextRelease: {
type: 'patch',
version: '2.1.1',
channel: '2.x',
gitTag: 'v2.1.1',
name: 'v2.1.1',
gitHead: 'v2.1.1',
type: "patch",
version: "2.1.1",
channel: "2.x",
gitTag: "v2.1.1",
name: "v2.1.1",
gitHead: "v2.1.1",
},
});
});
test('Return versions merged between release branches', (t) => {
test("Return versions merged between release branches", (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
name: "master",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null, 'next']},
{gitTag: 'v1.1.0', version: '1.1.0', channels: ['next']},
{gitTag: 'v2.0.0', version: '2.0.0', channels: ['next-major']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null, "next"] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: ["next"] },
{ gitTag: "v2.0.0", version: "2.0.0", channels: ["next-major"] },
],
},
branches: [{name: 'master'}, {name: 'next', channel: 'next'}, {name: 'next-major', channel: 'next-major'}],
options: {tagFormat: `v\${version}`},
branches: [{ name: "master" }, { name: "next", channel: "next" }, { name: "next-major", channel: "next-major" }],
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {
lastRelease: {
version: '1.1.0',
gitTag: 'v1.1.0',
name: 'v1.1.0',
gitHead: 'v1.1.0',
channels: ['next'],
version: "1.1.0",
gitTag: "v1.1.0",
name: "v1.1.0",
gitHead: "v1.1.0",
channels: ["next"],
},
currentRelease: {
type: 'major',
version: '2.0.0',
channels: ['next-major'],
gitTag: 'v2.0.0',
name: 'v2.0.0',
gitHead: 'v2.0.0',
type: "major",
version: "2.0.0",
channels: ["next-major"],
gitTag: "v2.0.0",
name: "v2.0.0",
gitHead: "v2.0.0",
},
nextRelease: {
type: 'major',
version: '2.0.0',
type: "major",
version: "2.0.0",
channel: null,
gitTag: 'v2.0.0',
name: 'v2.0.0',
gitHead: 'v2.0.0',
gitTag: "v2.0.0",
name: "v2.0.0",
gitHead: "v2.0.0",
},
});
});
test('Return releases sorted by ascending order', (t) => {
test("Return releases sorted by ascending order", (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
name: "master",
tags: [
{gitTag: 'v2.0.0', version: '2.0.0', channels: ['next-major']},
{gitTag: 'v1.1.0', version: '1.1.0', channels: ['next']},
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null, 'next']},
{ gitTag: "v2.0.0", version: "2.0.0", channels: ["next-major"] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: ["next"] },
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null, "next"] },
],
},
branches: [{name: 'master'}, {name: 'next', channel: 'next'}, {name: 'next-major', channel: 'next-major'}],
options: {tagFormat: `v\${version}`},
branches: [{ name: "master" }, { name: "next", channel: "next" }, { name: "next-major", channel: "next-major" }],
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {
lastRelease: {version: '1.1.0', gitTag: 'v1.1.0', name: 'v1.1.0', gitHead: 'v1.1.0', channels: ['next']},
lastRelease: { version: "1.1.0", gitTag: "v1.1.0", name: "v1.1.0", gitHead: "v1.1.0", channels: ["next"] },
currentRelease: {
type: 'major',
version: '2.0.0',
channels: ['next-major'],
gitTag: 'v2.0.0',
name: 'v2.0.0',
gitHead: 'v2.0.0',
type: "major",
version: "2.0.0",
channels: ["next-major"],
gitTag: "v2.0.0",
name: "v2.0.0",
gitHead: "v2.0.0",
},
nextRelease: {
type: 'major',
version: '2.0.0',
type: "major",
version: "2.0.0",
channel: null,
gitTag: 'v2.0.0',
name: 'v2.0.0',
gitHead: 'v2.0.0',
gitTag: "v2.0.0",
name: "v2.0.0",
gitHead: "v2.0.0",
},
});
});
test('No lastRelease', (t) => {
test("No lastRelease", (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: ['next']}],
name: "master",
tags: [{ gitTag: "v1.0.0", version: "1.0.0", channels: ["next"] }],
},
branches: [{name: 'master'}, {name: 'next', channel: 'next'}],
options: {tagFormat: `v\${version}`},
branches: [{ name: "master" }, { name: "next", channel: "next" }],
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {
lastRelease: {},
currentRelease: {
type: 'major',
version: '1.0.0',
channels: ['next'],
gitTag: 'v1.0.0',
name: 'v1.0.0',
gitHead: 'v1.0.0',
type: "major",
version: "1.0.0",
channels: ["next"],
gitTag: "v1.0.0",
name: "v1.0.0",
gitHead: "v1.0.0",
},
nextRelease: {
type: 'major',
version: '1.0.0',
type: "major",
version: "1.0.0",
channel: null,
gitTag: 'v1.0.0',
name: 'v1.0.0',
gitHead: 'v1.0.0',
gitTag: "v1.0.0",
name: "v1.0.0",
gitHead: "v1.0.0",
},
});
});
test('Ignore pre-release versions', (t) => {
test("Ignore pre-release versions", (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
name: "master",
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null, 'next']},
{gitTag: 'v1.1.0', version: '1.1.0', channels: ['next']},
{gitTag: 'v2.0.0-alpha.1', version: '2.0.0-alpha.1', channels: ['alpha']},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null, "next"] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: ["next"] },
{ gitTag: "v2.0.0-alpha.1", version: "2.0.0-alpha.1", channels: ["alpha"] },
],
},
branches: [
{name: 'master'},
{name: 'next', channel: 'next'},
{name: 'alpha', type: 'prerelease', channel: 'alpha'},
{ name: "master" },
{ name: "next", channel: "next" },
{ name: "alpha", type: "prerelease", channel: "alpha" },
],
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.deepEqual(result, {
lastRelease: {version: '1.0.0', channels: [null, 'next'], gitTag: 'v1.0.0', name: 'v1.0.0', gitHead: 'v1.0.0'},
lastRelease: { version: "1.0.0", channels: [null, "next"], gitTag: "v1.0.0", name: "v1.0.0", gitHead: "v1.0.0" },
currentRelease: {
type: 'minor',
version: '1.1.0',
channels: ['next'],
gitTag: 'v1.1.0',
name: 'v1.1.0',
gitHead: 'v1.1.0',
type: "minor",
version: "1.1.0",
channels: ["next"],
gitTag: "v1.1.0",
name: "v1.1.0",
gitHead: "v1.1.0",
},
nextRelease: {
type: 'minor',
version: '1.1.0',
type: "minor",
version: "1.1.0",
channel: null,
gitTag: 'v1.1.0',
name: 'v1.1.0',
gitHead: 'v1.1.0',
gitTag: "v1.1.0",
name: "v1.1.0",
gitHead: "v1.1.0",
},
});
});
@@ -191,24 +191,24 @@ test('Ignore pre-release versions', (t) => {
test('Exclude versions merged from release to maintenance branch if they have the same "channel"', (t) => {
const result = getReleaseToAdd({
branch: {
name: '2.x',
channel: 'latest',
type: 'maintenance',
mergeRange: '>=2.0.0 <3.0.0',
name: "2.x",
channel: "latest",
type: "maintenance",
mergeRange: ">=2.0.0 <3.0.0",
tags: [
{gitTag: 'v2.0.0', version: '2.0.0', channels: [null]},
{gitTag: 'v2.0.0', version: '2.0.0', channels: [null]},
{gitTag: 'v2.1.0', version: '2.1.0', channels: [null]},
{gitTag: 'v2.1.1', version: '2.1.1', channels: [null]},
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0', version: '1.1.0', channels: [null]},
{ gitTag: "v2.0.0", version: "2.0.0", channels: [null] },
{ gitTag: "v2.0.0", version: "2.0.0", channels: [null] },
{ gitTag: "v2.1.0", version: "2.1.0", channels: [null] },
{ gitTag: "v2.1.1", version: "2.1.1", channels: [null] },
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: [null] },
],
},
branches: [
{name: '2.x', channel: 'latest'},
{name: 'master', channel: 'latest'},
{ name: "2.x", channel: "latest" },
{ name: "master", channel: "latest" },
],
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.is(result, undefined);
@@ -217,20 +217,20 @@ test('Exclude versions merged from release to maintenance branch if they have th
test('Exclude versions merged between release branches if they have the same "channel"', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
channel: 'latest',
name: "master",
channel: "latest",
tags: [
{gitTag: 'v1.0.0', channels: ['latest'], version: '1.0.0'},
{gitTag: 'v1.1.0', channels: ['latest'], version: '1.1.0'},
{gitTag: 'v2.0.0', channels: ['latest'], version: '2.0.0'},
{ gitTag: "v1.0.0", channels: ["latest"], version: "1.0.0" },
{ gitTag: "v1.1.0", channels: ["latest"], version: "1.1.0" },
{ gitTag: "v2.0.0", channels: ["latest"], version: "2.0.0" },
],
},
branches: [
{name: 'master', channel: 'latest'},
{name: 'next', channel: 'latest'},
{name: 'next-major', channel: 'latest'},
{ name: "master", channel: "latest" },
{ name: "next", channel: "latest" },
{ name: "next-major", channel: "latest" },
],
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.is(result, undefined);
@@ -239,43 +239,43 @@ test('Exclude versions merged between release branches if they have the same "ch
test('Exclude versions merged between release branches if they all have "channel" set to "false"', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
name: "master",
channel: false,
tags: [
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0', version: '1.1.0', channels: [null]},
{gitTag: 'v2.0.0', version: '2.0.0', channels: [null]},
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: [null] },
{ gitTag: "v2.0.0", version: "2.0.0", channels: [null] },
],
},
branches: [
{name: 'master', channel: false},
{name: 'next', channel: false},
{name: 'next-major', channel: false},
{ name: "master", channel: false },
{ name: "next", channel: false },
{ name: "next-major", channel: false },
],
options: {tagFormat: `v\${version}`},
options: { tagFormat: `v\${version}` },
});
t.is(result, undefined);
});
test('Exclude versions number less than the latest version already released on that branch', (t) => {
test("Exclude versions number less than the latest version already released on that branch", (t) => {
const result = getReleaseToAdd({
branch: {
name: '2.x',
channel: '2.x',
type: 'maintenance',
mergeRange: '>=2.0.0 <3.0.0',
name: "2.x",
channel: "2.x",
type: "maintenance",
mergeRange: ">=2.0.0 <3.0.0",
tags: [
{gitTag: 'v2.0.0', version: '2.0.0', channels: ['2.x']},
{gitTag: 'v2.0.0', version: '2.0.0', channels: [null]},
{gitTag: 'v2.1.0', version: '2.1.0', channels: [null]},
{gitTag: 'v2.1.1', version: '2.1.1', channels: [null, '2.x']},
{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]},
{gitTag: 'v1.1.0', version: '1.1.0', channels: [null]},
{ gitTag: "v2.0.0", version: "2.0.0", channels: ["2.x"] },
{ gitTag: "v2.0.0", version: "2.0.0", channels: [null] },
{ gitTag: "v2.1.0", version: "2.1.0", channels: [null] },
{ gitTag: "v2.1.1", version: "2.1.1", channels: [null, "2.x"] },
{ gitTag: "v1.0.0", version: "1.0.0", channels: [null] },
{ gitTag: "v1.1.0", version: "1.1.0", channels: [null] },
],
},
branches: [{name: '2.x', channel: '2.x'}, {name: 'master'}],
options: {tagFormat: `v\${version}`},
branches: [{ name: "2.x", channel: "2.x" }, { name: "master" }],
options: { tagFormat: `v\${version}` },
});
t.is(result, undefined);
+211 -211
View File
@@ -1,5 +1,5 @@
import test from 'ava';
import {temporaryDirectory} from 'tempy';
import test from "ava";
import { temporaryDirectory } from "tempy";
import {
addNote,
fetch,
@@ -15,8 +15,8 @@ import {
push,
repoUrl,
tag,
verifyTagName
} from '../lib/git.js';
verifyTagName,
} from "../lib/git.js";
import {
gitAddConfig,
gitAddNote,
@@ -33,385 +33,385 @@ import {
gitRepo,
gitShallowClone,
gitTagVersion,
initGit
} from './helpers/git-utils.js';
initGit,
} from "./helpers/git-utils.js";
test('Get the last commit sha', async (t) => {
test("Get the last commit sha", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
const result = await getGitHead({cwd});
const result = await getGitHead({ cwd });
t.is(result, commits[0].hash);
});
test('Throw error if the last commit sha cannot be found', async (t) => {
test("Throw error if the last commit sha cannot be found", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
await t.throwsAsync(getGitHead({cwd}));
await t.throwsAsync(getGitHead({ cwd }));
});
test('Unshallow and fetch repository', async (t) => {
test("Unshallow and fetch repository", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
let { cwd, repositoryUrl } = await gitRepo();
// Add commits to the master branch
await gitCommits(['First', 'Second'], {cwd});
await gitCommits(["First", "Second"], { cwd });
// Create a shallow clone with only 1 commit
cwd = await gitShallowClone(repositoryUrl);
// Verify the shallow clone contains only one commit
t.is((await gitGetCommits(undefined, {cwd})).length, 1);
t.is((await gitGetCommits(undefined, { cwd })).length, 1);
await fetch(repositoryUrl, 'master', 'master', {cwd});
await fetch(repositoryUrl, "master", "master", { cwd });
// Verify the shallow clone contains all the commits
t.is((await gitGetCommits(undefined, {cwd})).length, 2);
t.is((await gitGetCommits(undefined, { cwd })).length, 2);
});
test('Do not throw error when unshallow a complete repository', async (t) => {
test("Do not throw error when unshallow a complete repository", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitCheckout('second-branch', true, {cwd});
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'second-branch', {cwd});
const { cwd, repositoryUrl } = await gitRepo(true);
await gitCommits(["First"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
await gitCheckout("second-branch", true, { cwd });
await gitCommits(["Second"], { cwd });
await gitPush(repositoryUrl, "second-branch", { cwd });
await t.notThrowsAsync(fetch(repositoryUrl, 'master', 'master', {cwd}));
await t.notThrowsAsync(fetch(repositoryUrl, 'second-branch', 'master', {cwd}));
await t.notThrowsAsync(fetch(repositoryUrl, "master", "master", { cwd }));
await t.notThrowsAsync(fetch(repositoryUrl, "second-branch", "master", { cwd }));
});
test('Fetch all tags on a detached head repository', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
test("Fetch all tags on a detached head repository", async (t) => {
let { cwd, repositoryUrl } = await gitRepo();
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
await gitCommits(['Second'], {cwd});
await gitTagVersion('v1.0.1', undefined, {cwd});
const [commit] = await gitCommits(['Third'], {cwd});
await gitTagVersion('v1.1.0', undefined, {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitCommits(["First"], { cwd });
await gitTagVersion("v1.0.0", undefined, { cwd });
await gitCommits(["Second"], { cwd });
await gitTagVersion("v1.0.1", undefined, { cwd });
const [commit] = await gitCommits(["Third"], { cwd });
await gitTagVersion("v1.1.0", undefined, { cwd });
await gitPush(repositoryUrl, "master", { cwd });
cwd = await gitDetachedHead(repositoryUrl, commit.hash);
await fetch(repositoryUrl, 'master', 'master', {cwd});
await fetch(repositoryUrl, "master", "master", { cwd });
t.deepEqual((await getTags('master', {cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0'].sort());
t.deepEqual((await getTags("master", { cwd })).sort(), ["v1.0.0", "v1.0.1", "v1.1.0"].sort());
});
test('Fetch all tags on a repository with a detached head from branch (CircleCI)', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
test("Fetch all tags on a repository with a detached head from branch (CircleCI)", async (t) => {
let { cwd, repositoryUrl } = await gitRepo();
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
await gitCommits(['Second'], {cwd});
await gitTagVersion('v1.0.1', undefined, {cwd});
const [commit] = await gitCommits(['Third'], {cwd});
await gitTagVersion('v1.1.0', undefined, {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitCheckout('other-branch', true, {cwd});
await gitPush(repositoryUrl, 'other-branch', {cwd});
await gitCheckout('master', false, {cwd});
await gitCommits(['Fourth'], {cwd});
await gitTagVersion('v2.0.0', undefined, {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
cwd = await gitDetachedHeadFromBranch(repositoryUrl, 'other-branch', commit.hash);
await gitCommits(["First"], { cwd });
await gitTagVersion("v1.0.0", undefined, { cwd });
await gitCommits(["Second"], { cwd });
await gitTagVersion("v1.0.1", undefined, { cwd });
const [commit] = await gitCommits(["Third"], { cwd });
await gitTagVersion("v1.1.0", undefined, { cwd });
await gitPush(repositoryUrl, "master", { cwd });
await gitCheckout("other-branch", true, { cwd });
await gitPush(repositoryUrl, "other-branch", { cwd });
await gitCheckout("master", false, { cwd });
await gitCommits(["Fourth"], { cwd });
await gitTagVersion("v2.0.0", undefined, { cwd });
await gitPush(repositoryUrl, "master", { cwd });
cwd = await gitDetachedHeadFromBranch(repositoryUrl, "other-branch", commit.hash);
await fetch(repositoryUrl, 'master', 'other-branch', {cwd});
await fetch(repositoryUrl, 'other-branch', 'other-branch', {cwd});
await fetch(repositoryUrl, "master", "other-branch", { cwd });
await fetch(repositoryUrl, "other-branch", "other-branch", { cwd });
t.deepEqual((await getTags('other-branch', {cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0'].sort());
t.deepEqual((await getTags('master', {cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0', 'v2.0.0'].sort());
t.deepEqual((await getTags("other-branch", { cwd })).sort(), ["v1.0.0", "v1.0.1", "v1.1.0"].sort());
t.deepEqual((await getTags("master", { cwd })).sort(), ["v1.0.0", "v1.0.1", "v1.1.0", "v2.0.0"].sort());
});
test('Fetch all tags on a detached head repository with outdated cached repo (GitLab CI)', async (t) => {
const {cwd, repositoryUrl} = await gitRepo();
test("Fetch all tags on a detached head repository with outdated cached repo (GitLab CI)", async (t) => {
const { cwd, repositoryUrl } = await gitRepo();
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
await gitCommits(['Second'], {cwd});
await gitTagVersion('v1.0.1', undefined, {cwd});
let [commit] = await gitCommits(['Third'], {cwd});
await gitTagVersion('v1.1.0', undefined, {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitCommits(["First"], { cwd });
await gitTagVersion("v1.0.0", undefined, { cwd });
await gitCommits(["Second"], { cwd });
await gitTagVersion("v1.0.1", undefined, { cwd });
let [commit] = await gitCommits(["Third"], { cwd });
await gitTagVersion("v1.1.0", undefined, { cwd });
await gitPush(repositoryUrl, "master", { cwd });
// Create a clone (as first CI run would)
const cloneCwd = await gitShallowClone(repositoryUrl);
await gitFetch(repositoryUrl, {cwd: cloneCwd});
await gitCheckout(commit.hash, false, {cwd: cloneCwd});
await gitFetch(repositoryUrl, { cwd: cloneCwd });
await gitCheckout(commit.hash, false, { cwd: cloneCwd });
// Push tag to remote
[commit] = await gitCommits(['Fourth'], {cwd});
await gitTagVersion('v1.2.0', undefined, {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
[commit] = await gitCommits(["Fourth"], { cwd });
await gitTagVersion("v1.2.0", undefined, { cwd });
await gitPush(repositoryUrl, "master", { cwd });
// Fetch on the cached repo and make detached head, leaving master outdated
await fetch(repositoryUrl, 'master', 'master', {cwd: cloneCwd});
await gitCheckout(commit.hash, false, {cwd: cloneCwd});
await fetch(repositoryUrl, "master", "master", { cwd: cloneCwd });
await gitCheckout(commit.hash, false, { cwd: cloneCwd });
t.deepEqual((await getTags('master', {cwd: cloneCwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0', 'v1.2.0'].sort());
t.deepEqual((await getTags("master", { cwd: cloneCwd })).sort(), ["v1.0.0", "v1.0.1", "v1.1.0", "v1.2.0"].sort());
});
test('Verify if a branch exists', async (t) => {
test("Verify if a branch exists", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
await gitCommits(['First'], {cwd});
await gitCommits(["First"], { cwd });
// Create the new branch 'other-branch' from master
await gitCheckout('other-branch', true, {cwd});
await gitCheckout("other-branch", true, { cwd });
// Add commits to the 'other-branch' branch
await gitCommits(['Second'], {cwd});
await gitCommits(["Second"], { cwd });
t.true(await isRefExists('master', {cwd}));
t.true(await isRefExists('other-branch', {cwd}));
t.falsy(await isRefExists('next', {cwd}));
t.true(await isRefExists("master", { cwd }));
t.true(await isRefExists("other-branch", { cwd }));
t.falsy(await isRefExists("next", { cwd }));
});
test('Get all branches', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitCheckout('second-branch', true, {cwd});
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'second-branch', {cwd});
await gitCheckout('third-branch', true, {cwd});
await gitCommits(['Third'], {cwd});
await gitPush(repositoryUrl, 'third-branch', {cwd});
test("Get all branches", async (t) => {
const { cwd, repositoryUrl } = await gitRepo(true);
await gitCommits(["First"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
await gitCheckout("second-branch", true, { cwd });
await gitCommits(["Second"], { cwd });
await gitPush(repositoryUrl, "second-branch", { cwd });
await gitCheckout("third-branch", true, { cwd });
await gitCommits(["Third"], { cwd });
await gitPush(repositoryUrl, "third-branch", { cwd });
t.deepEqual((await getBranches(repositoryUrl, {cwd})).sort(), ['master', 'second-branch', 'third-branch'].sort());
t.deepEqual((await getBranches(repositoryUrl, { cwd })).sort(), ["master", "second-branch", "third-branch"].sort());
});
test('Return empty array if there are no branches', async (t) => {
const {cwd, repositoryUrl} = await initGit(true);
t.deepEqual(await getBranches(repositoryUrl, {cwd}), []);
test("Return empty array if there are no branches", async (t) => {
const { cwd, repositoryUrl } = await initGit(true);
t.deepEqual(await getBranches(repositoryUrl, { cwd }), []);
});
test('Get the commit sha for a given tag', async (t) => {
test("Get the commit sha for a given tag", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
// Create the tag corresponding to version 1.0.0
await gitTagVersion('v1.0.0', undefined, {cwd});
await gitTagVersion("v1.0.0", undefined, { cwd });
t.is(await getTagHead('v1.0.0', {cwd}), commits[0].hash);
t.is(await getTagHead("v1.0.0", { cwd }), commits[0].hash);
});
test('Return git remote repository url from config', async (t) => {
test("Return git remote repository url from config", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add remote.origin.url config
await gitAddConfig('remote.origin.url', 'git@hostname.com:owner/package.git', {cwd});
await gitAddConfig("remote.origin.url", "git@hostname.com:owner/package.git", { cwd });
t.is(await repoUrl({cwd}), 'git@hostname.com:owner/package.git');
t.is(await repoUrl({ cwd }), "git@hostname.com:owner/package.git");
});
test('Return git remote repository url set while cloning', async (t) => {
test("Return git remote repository url set while cloning", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
let { cwd, repositoryUrl } = await gitRepo();
await gitCommits(["First"], { cwd });
// Create a clone
cwd = await gitShallowClone(repositoryUrl);
t.is(await repoUrl({cwd}), repositoryUrl);
t.is(await repoUrl({ cwd }), repositoryUrl);
});
test('Return falsy if git repository url is not set', async (t) => {
test("Return falsy if git repository url is not set", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
t.falsy(await repoUrl({cwd}));
t.falsy(await repoUrl({ cwd }));
});
test('Add tag on head commit', async (t) => {
test("Add tag on head commit", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const commits = await gitCommits(['Test commit'], {cwd});
const { cwd } = await gitRepo();
const commits = await gitCommits(["Test commit"], { cwd });
await tag('tag_name', 'HEAD', {cwd});
await tag("tag_name", "HEAD", { cwd });
await t.is(await gitCommitTag(commits[0].hash, {cwd}), 'tag_name');
await t.is(await gitCommitTag(commits[0].hash, { cwd }), "tag_name");
});
test('Push tag to remote repository', async (t) => {
test("Push tag to remote repository", async (t) => {
// Create a git repository with a remote, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
const commits = await gitCommits(['Test commit'], {cwd});
const { cwd, repositoryUrl } = await gitRepo(true);
const commits = await gitCommits(["Test commit"], { cwd });
await tag('tag_name', 'HEAD', {cwd});
await push(repositoryUrl, {cwd});
await tag("tag_name", "HEAD", { cwd });
await push(repositoryUrl, { cwd });
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
t.is(await gitRemoteTagHead(repositoryUrl, "tag_name", { cwd }), commits[0].hash);
});
test('Push tag to remote repository with remote branch ahead', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const commits = await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
test("Push tag to remote repository with remote branch ahead", async (t) => {
const { cwd, repositoryUrl } = await gitRepo(true);
const commits = await gitCommits(["First"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
const temporaryRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Second'], {cwd: temporaryRepo});
await gitPush('origin', 'master', {cwd: temporaryRepo});
await gitCommits(["Second"], { cwd: temporaryRepo });
await gitPush("origin", "master", { cwd: temporaryRepo });
await tag('tag_name', 'HEAD', {cwd});
await push(repositoryUrl, {cwd});
await tag("tag_name", "HEAD", { cwd });
await push(repositoryUrl, { cwd });
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
t.is(await gitRemoteTagHead(repositoryUrl, "tag_name", { cwd }), commits[0].hash);
});
test('Return "true" if in a Git repository', async (t) => {
// Create a git repository with a remote, set the current working directory at the root of the repo
const {cwd} = await gitRepo(true);
const { cwd } = await gitRepo(true);
t.true(await isGitRepo({cwd}));
t.true(await isGitRepo({ cwd }));
});
test('Return falsy if not in a Git repository', async (t) => {
test("Return falsy if not in a Git repository", async (t) => {
const cwd = temporaryDirectory();
t.falsy(await isGitRepo({cwd}));
t.falsy(await isGitRepo({ cwd }));
});
test('Return "true" for valid tag names', async (t) => {
t.true(await verifyTagName('1.0.0'));
t.true(await verifyTagName('v1.0.0'));
t.true(await verifyTagName('tag_name'));
t.true(await verifyTagName('tag/name'));
t.true(await verifyTagName("1.0.0"));
t.true(await verifyTagName("v1.0.0"));
t.true(await verifyTagName("tag_name"));
t.true(await verifyTagName("tag/name"));
});
test('Return falsy for invalid tag names', async (t) => {
t.falsy(await verifyTagName('?1.0.0'));
t.falsy(await verifyTagName('*1.0.0'));
t.falsy(await verifyTagName('[1.0.0]'));
t.falsy(await verifyTagName('1.0.0..'));
test("Return falsy for invalid tag names", async (t) => {
t.falsy(await verifyTagName("?1.0.0"));
t.falsy(await verifyTagName("*1.0.0"));
t.falsy(await verifyTagName("[1.0.0]"));
t.falsy(await verifyTagName("1.0.0.."));
});
test('Throws error if obtaining the tags fails', async (t) => {
test("Throws error if obtaining the tags fails", async (t) => {
const cwd = temporaryDirectory();
await t.throwsAsync(getTags('master', {cwd}));
await t.throwsAsync(getTags("master", { cwd }));
});
test('Return "true" if repository is up to date', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
const { cwd, repositoryUrl } = await gitRepo(true);
await gitCommits(["First"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
t.true(await isBranchUpToDate(repositoryUrl, "master", { cwd }));
});
test('Return falsy if repository is not up to date', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
test("Return falsy if repository is not up to date", async (t) => {
const { cwd, repositoryUrl } = await gitRepo(true);
await gitCommits(["First"], { cwd });
await gitCommits(["Second"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
t.true(await isBranchUpToDate(repositoryUrl, "master", { cwd }));
const temporaryRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Third'], {cwd: temporaryRepo});
await gitPush('origin', 'master', {cwd: temporaryRepo});
await gitCommits(["Third"], { cwd: temporaryRepo });
await gitPush("origin", "master", { cwd: temporaryRepo });
t.falsy(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
t.falsy(await isBranchUpToDate(repositoryUrl, "master", { cwd }));
});
test('Return falsy if detached head repository is not up to date', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
test("Return falsy if detached head repository is not up to date", async (t) => {
let { cwd, repositoryUrl } = await gitRepo();
const [commit] = await gitCommits(['First'], {cwd});
await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
const [commit] = await gitCommits(["First"], { cwd });
await gitCommits(["Second"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
cwd = await gitDetachedHead(repositoryUrl, commit.hash);
await fetch(repositoryUrl, 'master', 'master', {cwd});
await fetch(repositoryUrl, "master", "master", { cwd });
t.falsy(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
t.falsy(await isBranchUpToDate(repositoryUrl, "master", { cwd }));
});
test('Get a commit note', async (t) => {
test("Get a commit note", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
await gitAddNote(JSON.stringify({note: 'note'}), commits[0].hash, {cwd});
await gitAddNote(JSON.stringify({ note: "note" }), commits[0].hash, { cwd });
t.deepEqual(await getNote(commits[0].hash, {cwd}), {note: 'note'});
t.deepEqual(await getNote(commits[0].hash, { cwd }), { note: "note" });
});
test('Return empty object if there is no commit note', async (t) => {
test("Return empty object if there is no commit note", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
t.deepEqual(await getNote(commits[0].hash, {cwd}), {});
t.deepEqual(await getNote(commits[0].hash, { cwd }), {});
});
test('Throw error if a commit note in invalid', async (t) => {
test("Throw error if a commit note in invalid", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
await gitAddNote('non-json note', commits[0].hash, {cwd});
await gitAddNote("non-json note", commits[0].hash, { cwd });
await t.throwsAsync(getNote(commits[0].hash, {cwd}));
await t.throwsAsync(getNote(commits[0].hash, { cwd }));
});
test('Add a commit note', async (t) => {
test("Add a commit note", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
await addNote({note: 'note'}, commits[0].hash, {cwd});
await addNote({ note: "note" }, commits[0].hash, { cwd });
t.is(await gitGetNote(commits[0].hash, {cwd}), '{"note":"note"}');
t.is(await gitGetNote(commits[0].hash, { cwd }), '{"note":"note"}');
});
test('Overwrite a commit note', async (t) => {
test("Overwrite a commit note", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const { cwd } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First'], {cwd});
const commits = await gitCommits(["First"], { cwd });
await addNote({note: 'note'}, commits[0].hash, {cwd});
await addNote({note: 'note2'}, commits[0].hash, {cwd});
await addNote({ note: "note" }, commits[0].hash, { cwd });
await addNote({ note: "note2" }, commits[0].hash, { cwd });
t.is(await gitGetNote(commits[0].hash, {cwd}), '{"note":"note2"}');
t.is(await gitGetNote(commits[0].hash, { cwd }), '{"note":"note2"}');
});
test('Unshallow and fetch repository with notes', async (t) => {
test("Unshallow and fetch repository with notes", async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
let { cwd, repositoryUrl } = await gitRepo();
// Add commits to the master branch
const commits = await gitCommits(['First', 'Second'], {cwd});
await gitAddNote(JSON.stringify({note: 'note'}), commits[0].hash, {cwd});
const commits = await gitCommits(["First", "Second"], { cwd });
await gitAddNote(JSON.stringify({ note: "note" }), commits[0].hash, { cwd });
// Create a shallow clone with only 1 commit
cwd = await gitShallowClone(repositoryUrl);
// Verify the shallow clone doesn't contains the note
await t.throwsAsync(gitGetNote(commits[0].hash, {cwd}));
await t.throwsAsync(gitGetNote(commits[0].hash, { cwd }));
await fetch(repositoryUrl, 'master', 'master', {cwd});
await fetchNotes(repositoryUrl, {cwd});
await fetch(repositoryUrl, "master", "master", { cwd });
await fetchNotes(repositoryUrl, { cwd });
// Verify the shallow clone contains the note
t.is(await gitGetNote(commits[0].hash, {cwd}), '{"note":"note"}');
t.is(await gitGetNote(commits[0].hash, { cwd }), '{"note":"note"}');
});
test('Fetch all notes on a detached head repository', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
test("Fetch all notes on a detached head repository", async (t) => {
let { cwd, repositoryUrl } = await gitRepo();
await gitCommits(['First'], {cwd});
const [commit] = await gitCommits(['Second'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
await gitAddNote(JSON.stringify({note: 'note'}), commit.hash, {cwd});
await gitCommits(["First"], { cwd });
const [commit] = await gitCommits(["Second"], { cwd });
await gitPush(repositoryUrl, "master", { cwd });
await gitAddNote(JSON.stringify({ note: "note" }), commit.hash, { cwd });
cwd = await gitDetachedHead(repositoryUrl, commit.hash);
await fetch(repositoryUrl, 'master', 'master', {cwd});
await fetchNotes(repositoryUrl, {cwd});
await fetch(repositoryUrl, "master", "master", { cwd });
await fetchNotes(repositoryUrl, { cwd });
t.is(await gitGetNote(commit.hash, {cwd}), '{"note":"note"}');
t.is(await gitGetNote(commit.hash, { cwd }), '{"note":"note"}');
});
+28 -28
View File
@@ -1,18 +1,18 @@
import test from 'ava';
import {repeat} from 'lodash-es';
import hideSensitive from '../lib/hide-sensitive.js';
import {SECRET_MIN_SIZE, SECRET_REPLACEMENT} from '../lib/definitions/constants.js';
import test from "ava";
import { repeat } from "lodash-es";
import hideSensitive from "../lib/hide-sensitive.js";
import { SECRET_MIN_SIZE, SECRET_REPLACEMENT } from "../lib/definitions/constants.js";
test('Replace multiple sensitive environment variable values', (t) => {
const env = {SOME_PASSWORD: 'password', SOME_TOKEN: 'secret'};
test("Replace multiple sensitive environment variable values", (t) => {
const env = { SOME_PASSWORD: "password", SOME_TOKEN: "secret" };
t.is(
hideSensitive(env)(`https://user:${env.SOME_PASSWORD}@host.com?token=${env.SOME_TOKEN}`),
`https://user:${SECRET_REPLACEMENT}@host.com?token=${SECRET_REPLACEMENT}`
);
});
test('Replace multiple occurences of sensitive environment variable values', (t) => {
const env = {secretKey: 'secret'};
test("Replace multiple occurences of sensitive environment variable values", (t) => {
const env = { secretKey: "secret" };
t.is(
hideSensitive(env)(`https://user:${env.secretKey}@host.com?token=${env.secretKey}`),
`https://user:${SECRET_REPLACEMENT}@host.com?token=${SECRET_REPLACEMENT}`
@@ -20,28 +20,28 @@ test('Replace multiple occurences of sensitive environment variable values', (t)
});
test('Replace sensitive environment variable matching specific regex for "private"', (t) => {
const env = {privateKey: 'secret', GOPRIVATE: 'host.com'};
const env = { privateKey: "secret", GOPRIVATE: "host.com" };
t.is(hideSensitive(env)(`https://host.com?token=${env.privateKey}`), `https://host.com?token=${SECRET_REPLACEMENT}`);
});
test('Replace url-encoded environment variable', (t) => {
const env = {privateKey: 'secret '};
test("Replace url-encoded environment variable", (t) => {
const env = { privateKey: "secret " };
t.is(
hideSensitive(env)(`https://host.com?token=${encodeURI(env.privateKey)}`),
`https://host.com?token=${SECRET_REPLACEMENT}`
);
});
test('Escape regexp special characters', (t) => {
const env = {SOME_CREDENTIALS: 'p$^{.+}\\w[a-z]o.*rd'};
test("Escape regexp special characters", (t) => {
const env = { SOME_CREDENTIALS: "p$^{.+}\\w[a-z]o.*rd" };
t.is(
hideSensitive(env)(`https://user:${env.SOME_CREDENTIALS}@host.com`),
`https://user:${SECRET_REPLACEMENT}@host.com`
);
});
test('Escape regexp special characters in url-encoded environment variable', (t) => {
const env = {SOME_PASSWORD: 'secret password p$^{.+}\\w[a-z]o.*rd)('};
test("Escape regexp special characters in url-encoded environment variable", (t) => {
const env = { SOME_PASSWORD: "secret password p$^{.+}\\w[a-z]o.*rd)(" };
t.is(
hideSensitive(env)(`https://user:${encodeURI(env.SOME_PASSWORD)}@host.com`),
`https://user:${SECRET_REPLACEMENT}@host.com`
@@ -52,31 +52,31 @@ test('Accept "undefined" input', (t) => {
t.is(hideSensitive({})(), undefined);
});
test('Return same string if no environment variable has to be replaced', (t) => {
t.is(hideSensitive({})('test'), 'test');
test("Return same string if no environment variable has to be replaced", (t) => {
t.is(hideSensitive({})("test"), "test");
});
test('Exclude empty environment variables from the regexp', (t) => {
const env = {SOME_PASSWORD: 'password', SOME_TOKEN: ''};
test("Exclude empty environment variables from the regexp", (t) => {
const env = { SOME_PASSWORD: "password", SOME_TOKEN: "" };
t.is(
hideSensitive(env)(`https://user:${env.SOME_PASSWORD}@host.com?token=`),
`https://user:${SECRET_REPLACEMENT}@host.com?token=`
);
});
test('Exclude empty environment variables from the regexp if there is only empty ones', (t) => {
t.is(hideSensitive({SOME_PASSWORD: '', SOME_TOKEN: ' \n '})(`https://host.com?token=`), 'https://host.com?token=');
test("Exclude empty environment variables from the regexp if there is only empty ones", (t) => {
t.is(hideSensitive({ SOME_PASSWORD: "", SOME_TOKEN: " \n " })(`https://host.com?token=`), "https://host.com?token=");
});
test('Exclude nonsensitive GOPRIVATE environment variable for Golang projects from the regexp', (t) => {
const env = {GOPRIVATE: 'host.com'};
t.is(hideSensitive(env)(`https://host.com?token=`), 'https://host.com?token=');
test("Exclude nonsensitive GOPRIVATE environment variable for Golang projects from the regexp", (t) => {
const env = { GOPRIVATE: "host.com" };
t.is(hideSensitive(env)(`https://host.com?token=`), "https://host.com?token=");
});
test('Exclude environment variables with value shorter than SECRET_MIN_SIZE from the regexp', (t) => {
const SHORT_TOKEN = repeat('a', SECRET_MIN_SIZE - 1);
const LONG_TOKEN = repeat('b', SECRET_MIN_SIZE);
const env = {SHORT_TOKEN, LONG_TOKEN};
test("Exclude environment variables with value shorter than SECRET_MIN_SIZE from the regexp", (t) => {
const SHORT_TOKEN = repeat("a", SECRET_MIN_SIZE - 1);
const LONG_TOKEN = repeat("b", SECRET_MIN_SIZE);
const env = { SHORT_TOKEN, LONG_TOKEN };
t.is(
hideSensitive(env)(`https://user:${SHORT_TOKEN}@host.com?token=${LONG_TOKEN}`),
`https://user:${SHORT_TOKEN}@host.com?token=${SECRET_REPLACEMENT}`
+791 -737
View File
File diff suppressed because it is too large Load Diff
+325 -317
View File
File diff suppressed because it is too large Load Diff
+111 -108
View File
@@ -1,5 +1,5 @@
import test from 'ava';
import AggregateError from 'aggregate-error';
import test from "ava";
import AggregateError from "aggregate-error";
import {
extractErrors,
getEarliestVersion,
@@ -14,173 +14,176 @@ import {
isSameChannel,
lowest,
makeTag,
tagsToVersions
} from '../lib/utils.js';
tagsToVersions,
} from "../lib/utils.js";
test('extractErrors', (t) => {
const errors = [new Error('Error 1'), new Error('Error 2')];
test("extractErrors", (t) => {
const errors = [new Error("Error 1"), new Error("Error 2")];
t.deepEqual(extractErrors(new AggregateError(errors)), errors);
t.deepEqual(extractErrors(errors[0]), [errors[0]]);
});
test('tagsToVersions', (t) => {
t.deepEqual(tagsToVersions([{version: '1.0.0'}, {version: '1.1.0'}, {version: '1.2.0'}]), [
'1.0.0',
'1.1.0',
'1.2.0',
test("tagsToVersions", (t) => {
t.deepEqual(tagsToVersions([{ version: "1.0.0" }, { version: "1.1.0" }, { version: "1.2.0" }]), [
"1.0.0",
"1.1.0",
"1.2.0",
]);
});
test('isMajorRange', (t) => {
t.false(isMajorRange('1.1.x'));
t.false(isMajorRange('1.11.x'));
t.false(isMajorRange('11.1.x'));
t.false(isMajorRange('11.11.x'));
t.false(isMajorRange('1.1.X'));
t.false(isMajorRange('1.1.0'));
test("isMajorRange", (t) => {
t.false(isMajorRange("1.1.x"));
t.false(isMajorRange("1.11.x"));
t.false(isMajorRange("11.1.x"));
t.false(isMajorRange("11.11.x"));
t.false(isMajorRange("1.1.X"));
t.false(isMajorRange("1.1.0"));
t.true(isMajorRange('1.x.x'));
t.true(isMajorRange('11.x.x'));
t.true(isMajorRange('1.X.X'));
t.true(isMajorRange('1.x'));
t.true(isMajorRange('11.x'));
t.true(isMajorRange('1.X'));
t.true(isMajorRange("1.x.x"));
t.true(isMajorRange("11.x.x"));
t.true(isMajorRange("1.X.X"));
t.true(isMajorRange("1.x"));
t.true(isMajorRange("11.x"));
t.true(isMajorRange("1.X"));
});
test('isMaintenanceRange', (t) => {
t.true(isMaintenanceRange('1.1.x'));
t.true(isMaintenanceRange('11.1.x'));
t.true(isMaintenanceRange('11.11.x'));
t.true(isMaintenanceRange('1.11.x'));
t.true(isMaintenanceRange('1.x.x'));
t.true(isMaintenanceRange('11.x.x'));
t.true(isMaintenanceRange('1.x'));
t.true(isMaintenanceRange('11.x'));
t.true(isMaintenanceRange('1.1.X'));
t.true(isMaintenanceRange('1.X.X'));
t.true(isMaintenanceRange('1.X'));
test("isMaintenanceRange", (t) => {
t.true(isMaintenanceRange("1.1.x"));
t.true(isMaintenanceRange("11.1.x"));
t.true(isMaintenanceRange("11.11.x"));
t.true(isMaintenanceRange("1.11.x"));
t.true(isMaintenanceRange("1.x.x"));
t.true(isMaintenanceRange("11.x.x"));
t.true(isMaintenanceRange("1.x"));
t.true(isMaintenanceRange("11.x"));
t.true(isMaintenanceRange("1.1.X"));
t.true(isMaintenanceRange("1.X.X"));
t.true(isMaintenanceRange("1.X"));
t.false(isMaintenanceRange('1.1.0'));
t.false(isMaintenanceRange('11.1.0'));
t.false(isMaintenanceRange('1.11.0'));
t.false(isMaintenanceRange('11.11.0'));
t.false(isMaintenanceRange('~1.0.0'));
t.false(isMaintenanceRange('^1.0.0'));
t.false(isMaintenanceRange("1.1.0"));
t.false(isMaintenanceRange("11.1.0"));
t.false(isMaintenanceRange("1.11.0"));
t.false(isMaintenanceRange("11.11.0"));
t.false(isMaintenanceRange("~1.0.0"));
t.false(isMaintenanceRange("^1.0.0"));
});
test('getUpperBound', (t) => {
t.is(getUpperBound('1.x.x'), '2.0.0');
t.is(getUpperBound('1.X.X'), '2.0.0');
t.is(getUpperBound('10.x.x'), '11.0.0');
t.is(getUpperBound('1.x'), '2.0.0');
t.is(getUpperBound('10.x'), '11.0.0');
t.is(getUpperBound('1.0.x'), '1.1.0');
t.is(getUpperBound('10.0.x'), '10.1.0');
t.is(getUpperBound('10.10.x'), '10.11.0');
t.is(getUpperBound('1.0.0'), '1.0.0');
t.is(getUpperBound('10.0.0'), '10.0.0');
test("getUpperBound", (t) => {
t.is(getUpperBound("1.x.x"), "2.0.0");
t.is(getUpperBound("1.X.X"), "2.0.0");
t.is(getUpperBound("10.x.x"), "11.0.0");
t.is(getUpperBound("1.x"), "2.0.0");
t.is(getUpperBound("10.x"), "11.0.0");
t.is(getUpperBound("1.0.x"), "1.1.0");
t.is(getUpperBound("10.0.x"), "10.1.0");
t.is(getUpperBound("10.10.x"), "10.11.0");
t.is(getUpperBound("1.0.0"), "1.0.0");
t.is(getUpperBound("10.0.0"), "10.0.0");
t.is(getUpperBound('foo'), undefined);
t.is(getUpperBound("foo"), undefined);
});
test('getLowerBound', (t) => {
t.is(getLowerBound('1.x.x'), '1.0.0');
t.is(getLowerBound('1.X.X'), '1.0.0');
t.is(getLowerBound('10.x.x'), '10.0.0');
t.is(getLowerBound('1.x'), '1.0.0');
t.is(getLowerBound('10.x'), '10.0.0');
t.is(getLowerBound('1.0.x'), '1.0.0');
t.is(getLowerBound('10.0.x'), '10.0.0');
t.is(getLowerBound('1.10.x'), '1.10.0');
t.is(getLowerBound('1.0.0'), '1.0.0');
t.is(getLowerBound('10.0.0'), '10.0.0');
test("getLowerBound", (t) => {
t.is(getLowerBound("1.x.x"), "1.0.0");
t.is(getLowerBound("1.X.X"), "1.0.0");
t.is(getLowerBound("10.x.x"), "10.0.0");
t.is(getLowerBound("1.x"), "1.0.0");
t.is(getLowerBound("10.x"), "10.0.0");
t.is(getLowerBound("1.0.x"), "1.0.0");
t.is(getLowerBound("10.0.x"), "10.0.0");
t.is(getLowerBound("1.10.x"), "1.10.0");
t.is(getLowerBound("1.0.0"), "1.0.0");
t.is(getLowerBound("10.0.0"), "10.0.0");
t.is(getLowerBound('foo'), undefined);
t.is(getLowerBound("foo"), undefined);
});
test('highest', (t) => {
t.is(highest('1.0.0', '2.0.0'), '2.0.0');
t.is(highest('1.1.1', '1.1.0'), '1.1.1');
t.is(highest(null, '1.0.0'), '1.0.0');
t.is(highest('1.0.0'), '1.0.0');
test("highest", (t) => {
t.is(highest("1.0.0", "2.0.0"), "2.0.0");
t.is(highest("1.1.1", "1.1.0"), "1.1.1");
t.is(highest(null, "1.0.0"), "1.0.0");
t.is(highest("1.0.0"), "1.0.0");
t.is(highest(), undefined);
});
test('lowest', (t) => {
t.is(lowest('1.0.0', '2.0.0'), '1.0.0');
t.is(lowest('1.1.1', '1.1.0'), '1.1.0');
t.is(lowest(null, '1.0.0'), '1.0.0');
test("lowest", (t) => {
t.is(lowest("1.0.0", "2.0.0"), "1.0.0");
t.is(lowest("1.1.1", "1.1.0"), "1.1.0");
t.is(lowest(null, "1.0.0"), "1.0.0");
t.is(lowest(), undefined);
});
test.serial('getLatestVersion', (t) => {
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.1', '1.0.0-alpha.1']), '1.2.0');
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2']), undefined);
test.serial("getLatestVersion", (t) => {
t.is(getLatestVersion(["1.2.3-alpha.3", "1.2.0", "1.0.1", "1.0.0-alpha.1"]), "1.2.0");
t.is(getLatestVersion(["1.2.3-alpha.3", "1.2.3-alpha.2"]), undefined);
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.1', '1.0.0-alpha.1']), '1.2.0');
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2']), undefined);
t.is(getLatestVersion(["1.2.3-alpha.3", "1.2.0", "1.0.1", "1.0.0-alpha.1"]), "1.2.0");
t.is(getLatestVersion(["1.2.3-alpha.3", "1.2.3-alpha.2"]), undefined);
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.1', '1.0.0-alpha.1'], {withPrerelease: true}), '1.2.3-alpha.3');
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2'], {withPrerelease: true}), '1.2.3-alpha.3');
t.is(
getLatestVersion(["1.2.3-alpha.3", "1.2.0", "1.0.1", "1.0.0-alpha.1"], { withPrerelease: true }),
"1.2.3-alpha.3"
);
t.is(getLatestVersion(["1.2.3-alpha.3", "1.2.3-alpha.2"], { withPrerelease: true }), "1.2.3-alpha.3");
t.is(getLatestVersion([]), undefined);
});
test.serial('getEarliestVersion', (t) => {
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.0', '1.0.1-alpha.1']), '1.0.0');
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2']), undefined);
test.serial("getEarliestVersion", (t) => {
t.is(getEarliestVersion(["1.2.3-alpha.3", "1.2.0", "1.0.0", "1.0.1-alpha.1"]), "1.0.0");
t.is(getEarliestVersion(["1.2.3-alpha.3", "1.2.3-alpha.2"]), undefined);
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.0', '1.0.1-alpha.1']), '1.0.0');
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2']), undefined);
t.is(getEarliestVersion(["1.2.3-alpha.3", "1.2.0", "1.0.0", "1.0.1-alpha.1"]), "1.0.0");
t.is(getEarliestVersion(["1.2.3-alpha.3", "1.2.3-alpha.2"]), undefined);
t.is(
getEarliestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.1', '1.0.0-alpha.1'], {withPrerelease: true}),
'1.0.0-alpha.1'
getEarliestVersion(["1.2.3-alpha.3", "1.2.0", "1.0.1", "1.0.0-alpha.1"], { withPrerelease: true }),
"1.0.0-alpha.1"
);
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2'], {withPrerelease: true}), '1.2.3-alpha.2');
t.is(getEarliestVersion(["1.2.3-alpha.3", "1.2.3-alpha.2"], { withPrerelease: true }), "1.2.3-alpha.2");
t.is(getEarliestVersion([]), undefined);
});
test('getFirstVersion', (t) => {
t.is(getFirstVersion(['1.2.0', '1.0.0', '1.3.0', '1.1.0', '1.4.0'], []), '1.0.0');
test("getFirstVersion", (t) => {
t.is(getFirstVersion(["1.2.0", "1.0.0", "1.3.0", "1.1.0", "1.4.0"], []), "1.0.0");
t.is(
getFirstVersion(
['1.2.0', '1.0.0', '1.3.0', '1.1.0', '1.4.0'],
["1.2.0", "1.0.0", "1.3.0", "1.1.0", "1.4.0"],
[
{name: 'master', tags: [{version: '1.0.0'}, {version: '1.1.0'}]},
{name: 'next', tags: [{version: '1.0.0'}, {version: '1.1.0'}, {version: '1.2.0'}]},
{ name: "master", tags: [{ version: "1.0.0" }, { version: "1.1.0" }] },
{ name: "next", tags: [{ version: "1.0.0" }, { version: "1.1.0" }, { version: "1.2.0" }] },
]
),
'1.3.0'
"1.3.0"
);
t.is(
getFirstVersion(
['1.2.0', '1.0.0', '1.1.0'],
["1.2.0", "1.0.0", "1.1.0"],
[
{name: 'master', tags: [{version: '1.0.0'}, {version: '1.1.0'}]},
{name: 'next', tags: [{version: '1.0.0'}, {version: '1.1.0'}, {version: '1.2.0'}]},
{ name: "master", tags: [{ version: "1.0.0" }, { version: "1.1.0" }] },
{ name: "next", tags: [{ version: "1.0.0" }, { version: "1.1.0" }, { version: "1.2.0" }] },
]
),
undefined
);
});
test('getRange', (t) => {
t.is(getRange('1.0.0', '1.1.0'), '>=1.0.0 <1.1.0');
t.is(getRange('1.0.0'), '>=1.0.0');
test("getRange", (t) => {
t.is(getRange("1.0.0", "1.1.0"), ">=1.0.0 <1.1.0");
t.is(getRange("1.0.0"), ">=1.0.0");
});
test('makeTag', (t) => {
t.is(makeTag(`v\${version}`, '1.0.0'), 'v1.0.0');
test("makeTag", (t) => {
t.is(makeTag(`v\${version}`, "1.0.0"), "v1.0.0");
});
test('isSameChannel', (t) => {
t.true(isSameChannel('next', 'next'));
test("isSameChannel", (t) => {
t.true(isSameChannel("next", "next"));
t.true(isSameChannel(null, undefined));
t.true(isSameChannel(false, undefined));
t.true(isSameChannel('', false));
t.true(isSameChannel("", false));
t.false(isSameChannel('next', false));
t.false(isSameChannel("next", false));
});
+53 -53
View File
@@ -1,117 +1,117 @@
import test from 'ava';
import {temporaryDirectory} from 'tempy';
import verify from '../lib/verify.js';
import {gitRepo} from './helpers/git-utils.js';
import test from "ava";
import { temporaryDirectory } from "tempy";
import verify from "../lib/verify.js";
import { gitRepo } from "./helpers/git-utils.js";
test('Throw a AggregateError', async (t) => {
const {cwd} = await gitRepo();
const options = {branches: [{name: 'master'}, {name: ''}]};
test("Throw a AggregateError", async (t) => {
const { cwd } = await gitRepo();
const options = { branches: [{ name: "master" }, { name: "" }] };
const errors = [...(await t.throwsAsync(verify({cwd, options}))).errors];
const errors = [...(await t.throwsAsync(verify({ cwd, options }))).errors];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'ENOREPOURL');
t.is(errors[0].name, "SemanticReleaseError");
t.is(errors[0].code, "ENOREPOURL");
t.truthy(errors[0].message);
t.truthy(errors[0].details);
t.is(errors[1].name, 'SemanticReleaseError');
t.is(errors[1].code, 'EINVALIDTAGFORMAT');
t.is(errors[1].name, "SemanticReleaseError");
t.is(errors[1].code, "EINVALIDTAGFORMAT");
t.truthy(errors[1].message);
t.truthy(errors[1].details);
t.is(errors[2].name, 'SemanticReleaseError');
t.is(errors[2].code, 'ETAGNOVERSION');
t.is(errors[2].name, "SemanticReleaseError");
t.is(errors[2].code, "ETAGNOVERSION");
t.truthy(errors[2].message);
t.truthy(errors[2].details);
t.is(errors[3].name, 'SemanticReleaseError');
t.is(errors[3].code, 'EINVALIDBRANCH');
t.is(errors[3].name, "SemanticReleaseError");
t.is(errors[3].code, "EINVALIDBRANCH");
t.truthy(errors[3].message);
t.truthy(errors[3].details);
});
test('Throw a SemanticReleaseError if does not run on a git repository', async (t) => {
test("Throw a SemanticReleaseError if does not run on a git repository", async (t) => {
const cwd = temporaryDirectory();
const options = {branches: []};
const options = { branches: [] };
const errors = [...(await t.throwsAsync(verify({cwd, options}))).errors];
const errors = [...(await t.throwsAsync(verify({ cwd, options }))).errors];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'ENOGITREPO');
t.is(errors[0].name, "SemanticReleaseError");
t.is(errors[0].code, "ENOGITREPO");
t.truthy(errors[0].message);
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError if the "tagFormat" is not valid', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: `?\${version}`, branches: []};
const { cwd, repositoryUrl } = await gitRepo(true);
const options = { repositoryUrl, tagFormat: `?\${version}`, branches: [] };
const errors = [...(await t.throwsAsync(verify({cwd, options}))).errors];
const errors = [...(await t.throwsAsync(verify({ cwd, options }))).errors];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'EINVALIDTAGFORMAT');
t.is(errors[0].name, "SemanticReleaseError");
t.is(errors[0].code, "EINVALIDTAGFORMAT");
t.truthy(errors[0].message);
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError if the "tagFormat" does not contains the "version" variable', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: 'test', branches: []};
const { cwd, repositoryUrl } = await gitRepo(true);
const options = { repositoryUrl, tagFormat: "test", branches: [] };
const errors = [...(await t.throwsAsync(verify({cwd, options}))).errors];
const errors = [...(await t.throwsAsync(verify({ cwd, options }))).errors];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'ETAGNOVERSION');
t.is(errors[0].name, "SemanticReleaseError");
t.is(errors[0].code, "ETAGNOVERSION");
t.truthy(errors[0].message);
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError if the "tagFormat" contains multiple "version" variables', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: `\${version}v\${version}`, branches: []};
const { cwd, repositoryUrl } = await gitRepo(true);
const options = { repositoryUrl, tagFormat: `\${version}v\${version}`, branches: [] };
const errors = [...(await t.throwsAsync(verify({cwd, options}))).errors];
const errors = [...(await t.throwsAsync(verify({ cwd, options }))).errors];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'ETAGNOVERSION');
t.is(errors[0].name, "SemanticReleaseError");
t.is(errors[0].code, "ETAGNOVERSION");
t.truthy(errors[0].message);
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError for each invalid branch', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
test("Throw a SemanticReleaseError for each invalid branch", async (t) => {
const { cwd, repositoryUrl } = await gitRepo(true);
const options = {
repositoryUrl,
tagFormat: `v\${version}`,
branches: [{name: ''}, {name: ' '}, {name: 1}, {}, {name: ''}, 1, 'master'],
branches: [{ name: "" }, { name: " " }, { name: 1 }, {}, { name: "" }, 1, "master"],
};
const errors = [...(await t.throwsAsync(verify({cwd, options}))).errors];
const errors = [...(await t.throwsAsync(verify({ cwd, options }))).errors];
t.is(errors[0].name, 'SemanticReleaseError');
t.is(errors[0].code, 'EINVALIDBRANCH');
t.is(errors[0].name, "SemanticReleaseError");
t.is(errors[0].code, "EINVALIDBRANCH");
t.truthy(errors[0].message);
t.truthy(errors[0].details);
t.is(errors[1].name, 'SemanticReleaseError');
t.is(errors[1].code, 'EINVALIDBRANCH');
t.is(errors[1].name, "SemanticReleaseError");
t.is(errors[1].code, "EINVALIDBRANCH");
t.truthy(errors[1].message);
t.truthy(errors[1].details);
t.is(errors[2].name, 'SemanticReleaseError');
t.is(errors[2].code, 'EINVALIDBRANCH');
t.is(errors[2].name, "SemanticReleaseError");
t.is(errors[2].code, "EINVALIDBRANCH");
t.truthy(errors[2].message);
t.truthy(errors[2].details);
t.is(errors[3].name, 'SemanticReleaseError');
t.is(errors[3].code, 'EINVALIDBRANCH');
t.is(errors[3].name, "SemanticReleaseError");
t.is(errors[3].code, "EINVALIDBRANCH");
t.truthy(errors[3].message);
t.truthy(errors[3].details);
t.is(errors[4].code, 'EINVALIDBRANCH');
t.is(errors[4].code, "EINVALIDBRANCH");
t.truthy(errors[4].message);
t.truthy(errors[4].details);
t.is(errors[5].code, 'EINVALIDBRANCH');
t.is(errors[5].code, "EINVALIDBRANCH");
t.truthy(errors[5].message);
t.truthy(errors[5].details);
});
test('Return "true" if all verification pass', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: `v\${version}`, branches: [{name: 'master'}]};
const { cwd, repositoryUrl } = await gitRepo(true);
const options = { repositoryUrl, tagFormat: `v\${version}`, branches: [{ name: "master" }] };
await t.notThrowsAsync(verify({cwd, options}));
await t.notThrowsAsync(verify({ cwd, options }));
});