Skip to content

Commit 020ea7d

Browse files
Killian Hamayadatravi
Killian Hamayada
andauthored
fix: use one note reference per tag to prevent conflicts (semantic-release#2085)
Co-authored-by: Matt Travi <[email protected]>
1 parent 6d2a6f1 commit 020ea7d

File tree

3 files changed

+48
-16
lines changed

3 files changed

+48
-16
lines changed

index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,15 @@ async function run(context, plugins) {
123123
if (options.dryRun) {
124124
logger.warn(`Skip ${nextRelease.gitTag} tag creation in dry-run mode`);
125125
} else {
126-
await addNote({ channels: [...currentRelease.channels, nextRelease.channel] }, nextRelease.gitHead, {
126+
await addNote({ channels: [...currentRelease.channels, nextRelease.channel] }, nextRelease.gitTag, {
127127
cwd,
128128
env,
129129
});
130130
await push(options.repositoryUrl, { cwd, env });
131-
await pushNotes(options.repositoryUrl, { cwd, env });
131+
await pushNotes(options.repositoryUrl, nextRelease.gitTag, {
132+
cwd,
133+
env,
134+
});
132135
logger.success(
133136
`Add ${nextRelease.channel ? `channel ${nextRelease.channel}` : "default channel"} to tag ${
134137
nextRelease.gitTag
@@ -203,9 +206,9 @@ async function run(context, plugins) {
203206
} else {
204207
// Create the tag before calling the publish plugins as some require the tag to exists
205208
await tag(nextRelease.gitTag, nextRelease.gitHead, { cwd, env });
206-
await addNote({ channels: [nextRelease.channel] }, nextRelease.gitHead, { cwd, env });
209+
await addNote({ channels: [nextRelease.channel] }, nextRelease.gitTag, { cwd, env });
207210
await push(options.repositoryUrl, { cwd, env });
208-
await pushNotes(options.repositoryUrl, { cwd, env });
211+
await pushNotes(options.repositoryUrl, nextRelease.gitTag, { cwd, env });
209212
logger.success(`Created tag ${nextRelease.gitTag}`);
210213
}
211214

lib/git.js

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import gitLogParser from "git-log-parser";
22
import getStream from "get-stream";
33
import { execa } from "execa";
44
import debugGit from "debug";
5+
import { merge } from "lodash-es";
56
import { GIT_NOTE_REF } from "./definitions/constants.js";
67

78
const debug = debugGit("semantic-release:git");
@@ -141,13 +142,9 @@ export async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
141142
*/
142143
export async function fetchNotes(repositoryUrl, execaOptions) {
143144
try {
144-
await execa(
145-
"git",
146-
["fetch", "--unshallow", repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`],
147-
execaOptions
148-
);
145+
await execa("git", ["fetch", "--unshallow", repositoryUrl, `+refs/notes/*:refs/notes/*`], execaOptions);
149146
} catch {
150-
await execa("git", ["fetch", repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`], {
147+
await execa("git", ["fetch", repositoryUrl, `+refs/notes/*:refs/notes/*`], {
151148
...execaOptions,
152149
reject: false,
153150
});
@@ -246,8 +243,8 @@ export async function push(repositoryUrl, execaOptions) {
246243
*
247244
* @throws {Error} if the push failed.
248245
*/
249-
export async function pushNotes(repositoryUrl, execaOptions) {
250-
await execa("git", ["push", repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
246+
export async function pushNotes(repositoryUrl, ref, execaOptions) {
247+
await execa("git", ["push", repositoryUrl, `refs/notes/${GIT_NOTE_REF}-${ref}`], execaOptions);
251248
}
252249

253250
/**
@@ -307,8 +304,26 @@ export async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
307304
* @return {Object} the parsed JSON note if there is one, an empty object otherwise.
308305
*/
309306
export async function getNote(ref, execaOptions) {
307+
const handleError = (error) => {
308+
if (error.exitCode === 1) {
309+
return { stdout: "{}" };
310+
}
311+
312+
debug(error);
313+
throw error;
314+
};
315+
310316
try {
311-
return JSON.parse((await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions)).stdout);
317+
return merge(
318+
JSON.parse(
319+
// Used for retro-compatibility
320+
(await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions).catch(handleError)).stdout
321+
),
322+
JSON.parse(
323+
(await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "show", ref], execaOptions).catch(handleError))
324+
.stdout
325+
)
326+
);
312327
} catch (error) {
313328
if (error.exitCode === 1) {
314329
return {};
@@ -327,5 +342,19 @@ export async function getNote(ref, execaOptions) {
327342
* @param {Object} [execaOpts] Options to pass to `execa`.
328343
*/
329344
export async function addNote(note, ref, execaOptions) {
330-
await execa("git", ["notes", "--ref", GIT_NOTE_REF, "add", "-f", "-m", JSON.stringify(note), ref], execaOptions);
345+
await execa(
346+
"git",
347+
["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "add", "-f", "-m", JSON.stringify(note), ref],
348+
execaOptions
349+
);
350+
}
351+
352+
/**
353+
* Get the reference of a tag
354+
*
355+
* @param {String} tag The tag name to get the reference of.
356+
* @param {Object} [execaOpts] Options to pass to `execa`.
357+
**/
358+
export async function getTagRef(tag, execaOptions) {
359+
return (await execa("git", ["show-ref", tag, "--hash"], execaOptions)).stdout;
331360
}

test/helpers/git-utils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ export async function rebase(ref, execaOptions) {
315315
* @param {Object} [execaOpts] Options to pass to `execa`.
316316
*/
317317
export async function gitAddNote(note, ref, execaOptions) {
318-
await execa("git", ["notes", "--ref", GIT_NOTE_REF, "add", "-m", note, ref], execaOptions);
318+
await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "add", "-m", note, ref], execaOptions);
319319
}
320320

321321
/**
@@ -325,5 +325,5 @@ export async function gitAddNote(note, ref, execaOptions) {
325325
* @param {Object} [execaOpts] Options to pass to `execa`.
326326
*/
327327
export async function gitGetNote(ref, execaOptions) {
328-
return (await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions)).stdout;
328+
return (await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "show", ref], execaOptions)).stdout;
329329
}

0 commit comments

Comments
 (0)