fix: fetch all release branches on CI
This commit is contained in:
parent
e63e753cf0
commit
b729183b4a
4
index.js
4
index.js
@ -18,7 +18,7 @@ const {extractErrors, makeTag} = require('./lib/utils');
|
|||||||
const getGitAuthUrl = require('./lib/get-git-auth-url');
|
const getGitAuthUrl = require('./lib/get-git-auth-url');
|
||||||
const getBranches = require('./lib/branches');
|
const getBranches = require('./lib/branches');
|
||||||
const getLogger = require('./lib/get-logger');
|
const getLogger = require('./lib/get-logger');
|
||||||
const {fetch, verifyAuth, isBranchUpToDate, getGitHead, tag, push} = require('./lib/git');
|
const {verifyAuth, isBranchUpToDate, getGitHead, tag, push} = require('./lib/git');
|
||||||
const getError = require('./lib/get-error');
|
const getError = require('./lib/get-error');
|
||||||
const {COMMIT_NAME, COMMIT_EMAIL} = require('./lib/definitions/constants');
|
const {COMMIT_NAME, COMMIT_EMAIL} = require('./lib/definitions/constants');
|
||||||
|
|
||||||
@ -53,8 +53,6 @@ async function run(context, plugins) {
|
|||||||
// Verify config
|
// Verify config
|
||||||
await verify(context);
|
await verify(context);
|
||||||
|
|
||||||
await fetch({cwd, env});
|
|
||||||
|
|
||||||
context.branches = await getBranches(context);
|
context.branches = await getBranches(context);
|
||||||
context.branch = context.branches.find(({name}) => name === ciBranch);
|
context.branch = context.branches.find(({name}) => name === ciBranch);
|
||||||
|
|
||||||
|
@ -3,20 +3,25 @@ const AggregateError = require('aggregate-error');
|
|||||||
const pEachSeries = require('p-each-series');
|
const pEachSeries = require('p-each-series');
|
||||||
const DEFINITIONS = require('../definitions/branches');
|
const DEFINITIONS = require('../definitions/branches');
|
||||||
const getError = require('../get-error');
|
const getError = require('../get-error');
|
||||||
const {verifyBranchName} = require('../git');
|
const {fetch, verifyBranchName} = require('../git');
|
||||||
const expand = require('./expand');
|
const expand = require('./expand');
|
||||||
const getTags = require('./get-tags');
|
const getTags = require('./get-tags');
|
||||||
const normalize = require('./normalize');
|
const normalize = require('./normalize');
|
||||||
|
|
||||||
module.exports = async context => {
|
module.exports = async context => {
|
||||||
const branches = await getTags(
|
const {cwd, env} = context;
|
||||||
|
|
||||||
|
const remoteBranches = await expand(
|
||||||
context,
|
context,
|
||||||
await expand(
|
context.options.branches.map(branch => (isString(branch) || isRegExp(branch) ? {name: branch} : branch))
|
||||||
context,
|
|
||||||
context.options.branches.map(branch => (isString(branch) || isRegExp(branch) ? {name: branch} : branch))
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await pEachSeries(remoteBranches, async ({name}) => {
|
||||||
|
await fetch(name, {cwd, env});
|
||||||
|
});
|
||||||
|
|
||||||
|
const branches = await getTags(context, remoteBranches);
|
||||||
|
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const branchesByType = Object.entries(DEFINITIONS).reduce(
|
const branchesByType = Object.entries(DEFINITIONS).reduce(
|
||||||
(branchesByType, [type, {filter}]) => ({[type]: branches.filter(filter), ...branchesByType}),
|
(branchesByType, [type, {filter}]) => ({[type]: branches.filter(filter), ...branchesByType}),
|
||||||
|
31
lib/git.js
31
lib/git.js
@ -1,4 +1,4 @@
|
|||||||
const {trimStart, matches, pick, memoize} = require('lodash');
|
const {matches, pick, memoize} = require('lodash');
|
||||||
const gitLogParser = require('git-log-parser');
|
const gitLogParser = require('git-log-parser');
|
||||||
const getStream = require('get-stream');
|
const getStream = require('get-stream');
|
||||||
const execa = require('execa');
|
const execa = require('execa');
|
||||||
@ -63,9 +63,9 @@ async function getCommits(from, to, execaOpts) {
|
|||||||
* @throws {Error} If the `git` command fails.
|
* @throws {Error} If the `git` command fails.
|
||||||
*/
|
*/
|
||||||
async function getBranches(execaOpts) {
|
async function getBranches(execaOpts) {
|
||||||
return (await execa.stdout('git', ['branch', '--list', '--no-color'], execaOpts))
|
return (await execa.stdout('git', ['ls-remote', '--heads', 'origin'], execaOpts))
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(branch => trimStart(branch, '*').trim())
|
.map(branch => branch.match(/^.+refs\/heads\/(.+)$/)[1])
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,13 +126,30 @@ async function isRefExists(ref, execaOpts) {
|
|||||||
/**
|
/**
|
||||||
* Unshallow the git repository if necessary and fetch all the tags.
|
* Unshallow the git repository if necessary and fetch all the tags.
|
||||||
*
|
*
|
||||||
|
* @param {String} branch The repository branch to fetch.
|
||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*/
|
*/
|
||||||
async function fetch(execaOpts) {
|
async function fetch(branch, execaOpts) {
|
||||||
|
const isLocalExists =
|
||||||
|
(await execa('git', ['rev-parse', '--verify', branch], {...execaOpts, reject: false})).code === 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await execa('git', ['fetch', '--unshallow', '--tags'], execaOpts);
|
await execa(
|
||||||
|
'git',
|
||||||
|
[
|
||||||
|
'fetch',
|
||||||
|
'--unshallow',
|
||||||
|
'--tags',
|
||||||
|
...(isLocalExists ? [] : ['origin', `+refs/heads/${branch}:refs/heads/${branch}`]),
|
||||||
|
],
|
||||||
|
execaOpts
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await execa('git', ['fetch', '--tags'], execaOpts);
|
await execa(
|
||||||
|
'git',
|
||||||
|
['fetch', '--tags', ...(isLocalExists ? [] : ['origin', `+refs/heads/${branch}:refs/heads/${branch}`])],
|
||||||
|
execaOpts
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +198,7 @@ async function isGitRepo(execaOpts) {
|
|||||||
* Verify the write access authorization to remote repository with push dry-run.
|
* Verify the write access authorization to remote repository with push dry-run.
|
||||||
*
|
*
|
||||||
* @param {String} repositoryUrl The remote repository URL.
|
* @param {String} repositoryUrl The remote repository URL.
|
||||||
* @param {String} branch The repositoru branch for which to verify write access.
|
* @param {String} branch The repository branch for which to verify write access.
|
||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*
|
*
|
||||||
* @throws {Error} if not authorized to push.
|
* @throws {Error} if not authorized to push.
|
||||||
|
@ -22,7 +22,7 @@ test('Enforce ranges with branching release workflow', async t => {
|
|||||||
{name: 'beta', prerelease: true, tags: []},
|
{name: 'beta', prerelease: true, tags: []},
|
||||||
{name: 'alpha', prerelease: true, tags: []},
|
{name: 'alpha', prerelease: true, tags: []},
|
||||||
];
|
];
|
||||||
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches});
|
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
|
||||||
|
|
||||||
let result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
|
let result = (await getBranches({options: {branches}})).map(({name, range}) => ({name, range}));
|
||||||
t.is(getBranch(result, '1.0.x').range, '>=1.0.0 <1.0.0', 'Cannot release on 1.0.x before a releasing on master');
|
t.is(getBranch(result, '1.0.x').range, '>=1.0.0 <1.0.0', 'Cannot release on 1.0.x before a releasing on master');
|
||||||
@ -145,7 +145,7 @@ test('Throw SemanticReleaseError for invalid configurations', async t => {
|
|||||||
{name: 'alpha', prerelease: 'alpha', tags: []},
|
{name: 'alpha', prerelease: 'alpha', tags: []},
|
||||||
{name: 'preview', prerelease: 'alpha', tags: []},
|
{name: 'preview', prerelease: 'alpha', tags: []},
|
||||||
];
|
];
|
||||||
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches});
|
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
|
||||||
const errors = [...(await t.throws(getBranches({options: {branches}})))];
|
const errors = [...(await t.throws(getBranches({options: {branches}})))];
|
||||||
|
|
||||||
t.is(errors[0].name, 'SemanticReleaseError');
|
t.is(errors[0].name, 'SemanticReleaseError');
|
||||||
@ -172,7 +172,7 @@ test('Throw SemanticReleaseError for invalid configurations', async t => {
|
|||||||
|
|
||||||
test('Throw a SemanticReleaseError if there is duplicate branches', async t => {
|
test('Throw a SemanticReleaseError if there is duplicate branches', async t => {
|
||||||
const branches = [{name: 'master', tags: []}, {name: 'master', tags: []}];
|
const branches = [{name: 'master', tags: []}, {name: 'master', tags: []}];
|
||||||
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches});
|
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
|
||||||
|
|
||||||
const errors = [...(await t.throws(getBranches({options: {branches}})))];
|
const errors = [...(await t.throws(getBranches({options: {branches}})))];
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ test('Throw a SemanticReleaseError if there is duplicate branches', async t => {
|
|||||||
|
|
||||||
test('Throw a SemanticReleaseError for each invalid branch name', async t => {
|
test('Throw a SemanticReleaseError for each invalid branch name', async t => {
|
||||||
const branches = [{name: '~master', tags: []}, {name: '^master', tags: []}];
|
const branches = [{name: '~master', tags: []}, {name: '^master', tags: []}];
|
||||||
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches});
|
const getBranches = proxyquire('../../lib/branches', {'./get-tags': () => branches, './expand': () => []});
|
||||||
|
|
||||||
const errors = [...(await t.throws(getBranches({options: {branches}})))];
|
const errors = [...(await t.throws(getBranches({options: {branches}})))];
|
||||||
|
|
||||||
|
@ -1,24 +1,32 @@
|
|||||||
import test from 'ava';
|
import test from 'ava';
|
||||||
import expand from '../../lib/branches/expand';
|
import expand from '../../lib/branches/expand';
|
||||||
import {gitRepo, gitCommits, gitCheckout} from '../helpers/git-utils';
|
import {gitRepo, gitCommits, gitCheckout, gitPush} from '../helpers/git-utils';
|
||||||
|
|
||||||
test('Expand branches defined with globs', async t => {
|
test('Expand branches defined with globs', async t => {
|
||||||
const {cwd} = await gitRepo();
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
await gitCommits(['First'], {cwd});
|
await gitCommits(['First'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'master', {cwd});
|
||||||
await gitCheckout('1.1.x', true, {cwd});
|
await gitCheckout('1.1.x', true, {cwd});
|
||||||
await gitCommits(['Second'], {cwd});
|
await gitCommits(['Second'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, '1.1.x', {cwd});
|
||||||
await gitCheckout('1.x.x', true, {cwd});
|
await gitCheckout('1.x.x', true, {cwd});
|
||||||
await gitCommits(['Third'], {cwd});
|
await gitCommits(['Third'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, '1.x.x', {cwd});
|
||||||
await gitCheckout('2.x', true, {cwd});
|
await gitCheckout('2.x', true, {cwd});
|
||||||
await gitCommits(['Fourth'], {cwd});
|
await gitCommits(['Fourth'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, '2.x', {cwd});
|
||||||
await gitCheckout('next', true, {cwd});
|
await gitCheckout('next', true, {cwd});
|
||||||
await gitCommits(['Fifth'], {cwd});
|
await gitCommits(['Fifth'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'next', {cwd});
|
||||||
await gitCheckout('pre/foo', true, {cwd});
|
await gitCheckout('pre/foo', true, {cwd});
|
||||||
await gitCommits(['Sixth'], {cwd});
|
await gitCommits(['Sixth'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'pre/foo', {cwd});
|
||||||
await gitCheckout('pre/bar', true, {cwd});
|
await gitCheckout('pre/bar', true, {cwd});
|
||||||
await gitCommits(['Seventh'], {cwd});
|
await gitCommits(['Seventh'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'pre/bar', {cwd});
|
||||||
await gitCheckout('beta', true, {cwd});
|
await gitCheckout('beta', true, {cwd});
|
||||||
await gitCommits(['Eighth'], {cwd});
|
await gitCommits(['Eighth'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'beta', {cwd});
|
||||||
|
|
||||||
const branches = [
|
const branches = [
|
||||||
// Should match all maintenance type branches
|
// Should match all maintenance type branches
|
||||||
|
@ -58,7 +58,7 @@ test('Unshallow and fetch repository', async t => {
|
|||||||
// Verify the shallow clone contains only one commit
|
// 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({cwd});
|
await fetch('master', {cwd});
|
||||||
|
|
||||||
// Verify the shallow clone contains all the commits
|
// Verify the shallow clone contains all the commits
|
||||||
t.is((await gitGetCommits(undefined, {cwd})).length, 2);
|
t.is((await gitGetCommits(undefined, {cwd})).length, 2);
|
||||||
@ -66,10 +66,15 @@ test('Unshallow and fetch repository', async t => {
|
|||||||
|
|
||||||
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
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
const {cwd} = await gitRepo(true);
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
// Add commits to the master branch
|
|
||||||
await gitCommits(['First'], {cwd});
|
await gitCommits(['First'], {cwd});
|
||||||
await t.notThrows(fetch({cwd}));
|
await gitPush(repositoryUrl, 'master', {cwd});
|
||||||
|
await gitCheckout('second-branch', true, {cwd});
|
||||||
|
await gitCommits(['Second'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'second-branch', {cwd});
|
||||||
|
|
||||||
|
await t.notThrows(fetch('master', {cwd}));
|
||||||
|
await t.notThrows(fetch('second-branch', {cwd}));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fetch all tags on a detached head repository', async t => {
|
test('Fetch all tags on a detached head repository', async t => {
|
||||||
@ -84,7 +89,7 @@ test('Fetch all tags on a detached head repository', async t => {
|
|||||||
await gitPush(repositoryUrl, 'master', {cwd});
|
await gitPush(repositoryUrl, 'master', {cwd});
|
||||||
cwd = await gitDetachedHead(repositoryUrl, commit.hash);
|
cwd = await gitDetachedHead(repositoryUrl, commit.hash);
|
||||||
|
|
||||||
await fetch({cwd});
|
await fetch('master', {cwd});
|
||||||
|
|
||||||
t.deepEqual((await getTags({cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0'].sort());
|
t.deepEqual((await getTags({cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0'].sort());
|
||||||
});
|
});
|
||||||
@ -122,12 +127,15 @@ test('Verify if a branch exists', async t => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Get all branches', async t => {
|
test('Get all branches', async t => {
|
||||||
const {cwd} = await gitRepo();
|
const {cwd, repositoryUrl} = await gitRepo(true);
|
||||||
await gitCommits(['First'], {cwd});
|
await gitCommits(['First'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'master', {cwd});
|
||||||
await gitCheckout('second-branch', true, {cwd});
|
await gitCheckout('second-branch', true, {cwd});
|
||||||
await gitCommits(['Second'], {cwd});
|
await gitCommits(['Second'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'second-branch', {cwd});
|
||||||
await gitCheckout('third-branch', true, {cwd});
|
await gitCheckout('third-branch', true, {cwd});
|
||||||
await gitCommits(['Third'], {cwd});
|
await gitCommits(['Third'], {cwd});
|
||||||
|
await gitPush(repositoryUrl, 'third-branch', {cwd});
|
||||||
|
|
||||||
t.deepEqual((await getBranches({cwd})).sort(), ['master', 'second-branch', 'third-branch'].sort());
|
t.deepEqual((await getBranches({cwd})).sort(), ['master', 'second-branch', 'third-branch'].sort());
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user