fix: fetch tags on repo cached by the CI
This commit is contained in:
parent
28b54800cd
commit
6b5b02ea75
17
lib/git.js
17
lib/git.js
@ -86,15 +86,22 @@ async function isRefExists(ref, execaOpts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unshallow the git repository if necessary and fetch all the tags.
|
* Fetch all the tags from a branch. Unshallow if necessary.
|
||||||
|
* This will update the local branch from the latest on the remote if:
|
||||||
|
* - The branch is not the one that triggered the CI
|
||||||
|
* - The CI created a detached head
|
||||||
|
*
|
||||||
|
* Otherwise it just calls `git fetch` without specifying the `refspec` option to avoid overwritting the head commit set by the CI.
|
||||||
|
*
|
||||||
|
* The goal is to retrieve the informations on all the release branches without "disturbing" the CI, leaving the trigger branch or the detached head intact.
|
||||||
*
|
*
|
||||||
* @param {String} repositoryUrl The remote repository URL.
|
* @param {String} repositoryUrl The remote repository URL.
|
||||||
* @param {String} branch The repository branch to fetch.
|
* @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(repositoryUrl, branch, ciBranch, execaOpts) {
|
async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
|
||||||
const isLocalExists =
|
const isDetachedHead =
|
||||||
(await execa('git', ['rev-parse', '--verify', branch], {...execaOpts, reject: false})).exitCode === 0;
|
(await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {...execaOpts, reject: false})).stdout === 'HEAD';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await execa(
|
await execa(
|
||||||
@ -103,7 +110,7 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
|
|||||||
'fetch',
|
'fetch',
|
||||||
'--unshallow',
|
'--unshallow',
|
||||||
'--tags',
|
'--tags',
|
||||||
...(branch === ciBranch && isLocalExists
|
...(branch === ciBranch && !isDetachedHead
|
||||||
? [repositoryUrl]
|
? [repositoryUrl]
|
||||||
: ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
|
: ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
|
||||||
],
|
],
|
||||||
@ -115,7 +122,7 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
|
|||||||
[
|
[
|
||||||
'fetch',
|
'fetch',
|
||||||
'--tags',
|
'--tags',
|
||||||
...(branch === ciBranch && isLocalExists
|
...(branch === ciBranch && !isDetachedHead
|
||||||
? [repositoryUrl]
|
? [repositoryUrl]
|
||||||
: ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
|
: ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
|
||||||
],
|
],
|
||||||
|
@ -32,6 +32,7 @@ import {
|
|||||||
gitDetachedHeadFromBranch,
|
gitDetachedHeadFromBranch,
|
||||||
gitAddNote,
|
gitAddNote,
|
||||||
gitGetNote,
|
gitGetNote,
|
||||||
|
gitFetch,
|
||||||
} from './helpers/git-utils';
|
} from './helpers/git-utils';
|
||||||
|
|
||||||
test('Get the last commit sha', async t => {
|
test('Get the last commit sha', async t => {
|
||||||
@ -99,7 +100,7 @@ test('Fetch all tags on a detached head repository', async t => {
|
|||||||
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', async t => {
|
test('Fetch all tags on a repository with a detached head from branch (CircleCI)', async t => {
|
||||||
let {cwd, repositoryUrl} = await gitRepo();
|
let {cwd, repositoryUrl} = await gitRepo();
|
||||||
|
|
||||||
await gitCommits(['First'], {cwd});
|
await gitCommits(['First'], {cwd});
|
||||||
@ -124,6 +125,34 @@ test('Fetch all tags on a repository with a detached head from branch', async t
|
|||||||
t.deepEqual((await getTags('master', {cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0', 'v2.0.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();
|
||||||
|
|
||||||
|
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});
|
||||||
|
|
||||||
|
// Push tag to remote
|
||||||
|
[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});
|
||||||
|
|
||||||
|
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
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
const {cwd} = await gitRepo();
|
const {cwd} = await gitRepo();
|
||||||
|
@ -109,6 +109,16 @@ export async function gitCheckout(branch, create, execaOpts) {
|
|||||||
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOpts);
|
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch current git repository.
|
||||||
|
*
|
||||||
|
* @param {String} repositoryUrl The repository remote URL.
|
||||||
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
|
*/
|
||||||
|
export async function gitFetch(repositoryUrl, execaOpts) {
|
||||||
|
await execa('git', ['fetch', repositoryUrl], execaOpts);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the HEAD sha.
|
* Get the HEAD sha.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user