Skip to content

Commit 22edba5

Browse files
committed
Support updating existing tag ref
1 parent 9d35d64 commit 22edba5

File tree

7 files changed

+119
-76
lines changed

7 files changed

+119
-76
lines changed

action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ inputs:
3636
custom_tag:
3737
description: "Custom tag name. If specified, it overrides bump settings."
3838
required: false
39+
force_update:
40+
description: "Updates the sha of a tag if it already exists"
41+
required: false
42+
default: "false"
3943
custom_release_rules:
4044
description: "Comma separated list of release rules. Format: `<keyword>:<release_type>`. Example: `hotfix:patch,pre-feat:preminor`."
4145
required: false

src/action.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
mapCustomReleaseRules,
1313
mergeWithDefaultChangelogRules,
1414
} from './utils';
15-
import { createTag } from './github';
15+
import { createTag, listTags } from './github';
1616
import { Await } from './ts';
1717

1818
export default async function main() {
@@ -22,6 +22,7 @@ export default async function main() {
2222
| 'false';
2323
const tagPrefix = core.getInput('tag_prefix');
2424
const customTag = core.getInput('custom_tag');
25+
const forceUpdate = /true/i.test(core.getInput('force_update'));
2526
const releaseBranches = core.getInput('release_branches');
2627
const preReleaseBranches = core.getInput('pre_release_branches');
2728
const appendToPreReleaseTag = core.getInput('append_to_pre_release_tag');
@@ -69,10 +70,8 @@ export default async function main() {
6970

7071
const prefixRegex = new RegExp(`^${tagPrefix}`);
7172

72-
const validTags = await getValidTags(
73-
prefixRegex,
74-
/true/i.test(shouldFetchAllTags)
75-
);
73+
const tags = await listTags(/true/i.test(shouldFetchAllTags));
74+
const validTags = await getValidTags(tags, prefixRegex);
7675
const latestTag = getLatestTag(validTags, prefixRegex, tagPrefix);
7776
const latestPrereleaseTag = getLatestPrereleaseTag(
7877
validTags,
@@ -218,7 +217,8 @@ export default async function main() {
218217
return;
219218
}
220219

221-
if (validTags.map((tag) => tag.name).includes(newTag)) {
220+
const tagExists = tags.map((tag) => tag.name).includes(newTag);
221+
if (tagExists && !forceUpdate) {
222222
core.info('This tag already exists. Skipping the tag creation.');
223223
return;
224224
}
@@ -228,5 +228,5 @@ export default async function main() {
228228
return;
229229
}
230230

231-
await createTag(newTag, createAnnotatedTag, commitRef);
231+
await createTag(newTag, createAnnotatedTag, tagExists, commitRef);
232232
}

src/github.ts

+20-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Await } from './ts';
44

55
let octokitSingleton: ReturnType<typeof getOctokit>;
66

7-
type Tag = {
7+
export type Tag = {
88
name: string;
99
commit: {
1010
sha: string;
@@ -15,6 +15,8 @@ type Tag = {
1515
node_id: string;
1616
};
1717

18+
export type Tags = Await<ReturnType<typeof listTags>>;
19+
1820
export function getOctokitSingleton() {
1921
if (octokitSingleton) {
2022
return octokitSingleton;
@@ -68,6 +70,7 @@ export async function compareCommits(baseRef: string, headRef: string) {
6870
export async function createTag(
6971
newTag: string,
7072
createAnnotatedTag: boolean,
73+
update: boolean,
7174
GITHUB_SHA: string
7275
) {
7376
const octokit = getOctokitSingleton();
@@ -85,10 +88,20 @@ export async function createTag(
8588
});
8689
}
8790

88-
core.debug(`Pushing new tag to the repo.`);
89-
await octokit.git.createRef({
90-
...context.repo,
91-
ref: `refs/tags/${newTag}`,
92-
sha: annotatedTag ? annotatedTag.data.sha : GITHUB_SHA,
93-
});
91+
if (update) {
92+
core.info(`Updating existing tag ${newTag} on the repo.`);
93+
await octokit.git.updateRef({
94+
...context.repo,
95+
ref: `tags/${newTag}`,
96+
sha: annotatedTag ? annotatedTag.data.sha : GITHUB_SHA,
97+
force: true,
98+
});
99+
} else {
100+
core.info(`Pushing new tag to the repo.`);
101+
await octokit.git.createRef({
102+
...context.repo,
103+
ref: `refs/tags/${newTag}`,
104+
sha: annotatedTag ? annotatedTag.data.sha : GITHUB_SHA,
105+
});
106+
}
94107
}

src/utils.ts

+3-11
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,16 @@ import * as core from '@actions/core';
22
import { prerelease, rcompare, valid } from 'semver';
33
// @ts-ignore
44
import DEFAULT_RELEASE_TYPES from '@semantic-release/commit-analyzer/lib/default-release-types';
5-
import { compareCommits, listTags } from './github';
5+
import { compareCommits, Tags } from './github';
66
import { defaultChangelogRules } from './defaults';
7-
import { Await } from './ts';
8-
9-
type Tags = Await<ReturnType<typeof listTags>>;
10-
11-
export async function getValidTags(
12-
prefixRegex: RegExp,
13-
shouldFetchAllTags: boolean
14-
) {
15-
const tags = await listTags(shouldFetchAllTags);
167

8+
export async function getValidTags(tags: Tags, prefixRegex: RegExp) {
179
const invalidTags = tags.filter(
1810
(tag) =>
1911
!prefixRegex.test(tag.name) || !valid(tag.name.replace(prefixRegex, ''))
2012
);
2113

22-
invalidTags.forEach((name) => core.debug(`Found Invalid Tag: ${name}.`));
14+
invalidTags.forEach((tag) => core.debug(`Found Invalid Tag: ${tag.name}.`));
2315

2416
const validTags = tags
2517
.filter(

0 commit comments

Comments
 (0)