Skip to content

Commit

Permalink
feat: use one note reference per tag to prevent conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
KillianHmyd committed May 12, 2022
1 parent ab45ab1 commit efaf0f9
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 23 deletions.
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ async function run(context, plugins) {
} else {
await addNote({channels: [...currentRelease.channels, nextRelease.channel]}, nextRelease.gitHead, {cwd, env});
await push(options.repositoryUrl, {cwd, env});
await pushNotes(options.repositoryUrl, {cwd, env});
await pushNotes(options.repositoryUrl, nextRelease.gitHead, {cwd, env});
logger.success(
`Add ${nextRelease.channel ? `channel ${nextRelease.channel}` : 'default channel'} to tag ${
nextRelease.gitTag
Expand Down Expand Up @@ -199,7 +199,7 @@ async function run(context, plugins) {
await tag(nextRelease.gitTag, nextRelease.gitHead, {cwd, env});
await addNote({channels: [nextRelease.channel]}, nextRelease.gitHead, {cwd, env});
await push(options.repositoryUrl, {cwd, env});
await pushNotes(options.repositoryUrl, {cwd, env});
await pushNotes(options.repositoryUrl, nextRelease.gitHead, {cwd, env});
logger.success(`Created tag ${nextRelease.gitTag}`);
}

Expand Down
11 changes: 9 additions & 2 deletions lib/branches/get-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const {template, escapeRegExp} = require('lodash');
const semver = require('semver');
const pReduce = require('p-reduce');
const debug = require('debug')('semantic-release:get-tags');
const {getTags, getNote} = require('../../lib/git');
const {getTags, getNote, getTagRef} = require('../../lib/git');

module.exports = async ({cwd, env, options: {tagFormat}}, branches) => {
// Generate a regex to parse tags formatted with `tagFormat`
Expand All @@ -19,7 +19,14 @@ module.exports = async ({cwd, env, options: {tagFormat}}, branches) => {
async (branchTags, tag) => {
const [, version] = tag.match(tagRegexp) || [];
return version && semver.valid(semver.clean(version))
? [...branchTags, {gitTag: tag, version, channels: (await getNote(tag, {cwd, env})).channels || [null]}]
? [
...branchTags,
{
gitTag: tag,
version,
channels: (await getNote(await getTagRef(tag, {cwd, env}), {cwd, env})).channels || [null],
},
]
: branchTags;
},
[]
Expand Down
49 changes: 38 additions & 11 deletions lib/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const gitLogParser = require('git-log-parser');
const getStream = require('get-stream');
const execa = require('execa');
const debug = require('debug')('semantic-release:git');
const {merge} = require('lodash');
const {GIT_NOTE_REF} = require('./definitions/constants');

Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', committerDate: {key: 'ci', type: Date}});
Expand Down Expand Up @@ -139,13 +140,9 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
*/
async function fetchNotes(repositoryUrl, execaOptions) {
try {
await execa(
'git',
['fetch', '--unshallow', repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`],
execaOptions
);
} catch {
await execa('git', ['fetch', repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`], {
await execa('git', ['fetch', '--unshallow', repositoryUrl, `+refs/notes/*:refs/notes/*`], execaOptions);
} catch (_) {
await execa('git', ['fetch', repositoryUrl, `+refs/notes/*:refs/notes/*`], {
...execaOptions,
reject: false,
});
Expand Down Expand Up @@ -244,8 +241,8 @@ async function push(repositoryUrl, execaOptions) {
*
* @throws {Error} if the push failed.
*/
async function pushNotes(repositoryUrl, execaOptions) {
await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
async function pushNotes(repositoryUrl, ref, execaOptions) {
await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}-${ref}`], execaOptions);
}

/**
Expand Down Expand Up @@ -306,7 +303,22 @@ async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
*/
async function getNote(ref, execaOptions) {
try {
return JSON.parse((await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout);
return merge(
JSON.parse(
// Used for retro-compatibility
(
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions).catch((error) => {
if (error.exitCode === 1) {
return '{}';
}

debug(error);
throw error;
})
).stdout || '{}'
),
JSON.parse((await execa('git', ['notes', '--ref', `${GIT_NOTE_REF}-${ref}`, 'show', ref], execaOptions)).stdout)
);
} catch (error) {
if (error.exitCode === 1) {
return {};
Expand All @@ -325,11 +337,26 @@ async function getNote(ref, execaOptions) {
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function addNote(note, ref, execaOptions) {
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-f', '-m', JSON.stringify(note), ref], execaOptions);
await execa(
'git',
['notes', '--ref', `${GIT_NOTE_REF}-${ref}`, 'add', '-f', '-m', JSON.stringify(note), ref],
execaOptions
);
}

/**
* Get the reference of a tag
*
* @param {String} tag The tag name to get the reference of.
* @param {Object} [execaOpts] Options to pass to `execa`.
**/
async function getTagRef(tag, execaOptions) {
return (await execa('git', ['show-ref', tag, '--hash'], execaOptions)).stdout;
}

module.exports = {
getTagHead,
getTagRef,
getTags,
getCommits,
getBranches,
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "semantic-release",
"name": "@payfit/semantic-release",
"description": "Automated semver compliant package publishing",
"version": "0.0.0-development",
"version": "0.0.0-notes-fix.6",
"author": "Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)",
"ava": {
"files": [
Expand Down
8 changes: 6 additions & 2 deletions test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const {npmView} = require('./helpers/npm-utils');
const gitbox = require('./helpers/gitbox');
const mockServer = require('./helpers/mockserver');
const npmRegistry = require('./helpers/npm-registry');
const {getTagRef} = require('../lib/git');

/* eslint camelcase: ["error", {properties: "never"}] */

Expand Down Expand Up @@ -250,8 +251,10 @@ test('Release patch, minor and major versions', async (t) => {
'dist-tags': {next: releasedVersion},
} = await npmView(packageName, npmTestEnv));
head = await gitHead({cwd});
let tagRef = await getTagRef(`v${version}`, {cwd});
t.is(tagRef, head);
t.is(releasedVersion, version);
t.is(await gitGetNote(`v${version}`, {cwd}), '{"channels":["next"]}');
t.is(await gitGetNote(tagRef, {cwd}), '{"channels":["next"]}');
t.is(await gitTagHead(`v${version}`, {cwd}), head);
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), head);
t.log(`+ released ${releasedVersion} on @next`);
Expand Down Expand Up @@ -298,7 +301,8 @@ test('Release patch, minor and major versions', async (t) => {
'dist-tags': {latest: releasedVersion},
} = await npmView(packageName, npmTestEnv));
t.is(releasedVersion, version);
t.is(await gitGetNote(`v${version}`, {cwd}), '{"channels":["next",null]}');
tagRef = await getTagRef(`v${version}`, {cwd});
t.is(await gitGetNote(tagRef, {cwd}), '{"channels":["next",null]}');
t.is(await gitTagHead(`v${version}`, {cwd}), await gitTagHead(`v${version}`, {cwd}));
t.is(await gitRemoteTagHead(authUrl, `v${version}`, {cwd}), await gitRemoteTagHead(authUrl, `v${version}`, {cwd}));
t.log(`+ added ${releasedVersion}`);
Expand Down

0 comments on commit efaf0f9

Please sign in to comment.