Skip to content

Commit fc68960

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

File tree

7 files changed

+132
-48
lines changed

7 files changed

+132
-48
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

+12-5
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,9 @@ 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(
26+
core.getInput('force_update')
27+
);
2528
const releaseBranches = core.getInput('release_branches');
2629
const preReleaseBranches = core.getInput('pre_release_branches');
2730
const appendToPreReleaseTag = core.getInput('append_to_pre_release_tag');
@@ -69,10 +72,13 @@ export default async function main() {
6972

7073
const prefixRegex = new RegExp(`^${tagPrefix}`);
7174

72-
const validTags = await getValidTags(
73-
prefixRegex,
75+
const tags = await listTags(
7476
/true/i.test(shouldFetchAllTags)
7577
);
78+
const validTags = await getValidTags(
79+
tags,
80+
prefixRegex
81+
);
7682
const latestTag = getLatestTag(validTags, prefixRegex, tagPrefix);
7783
const latestPrereleaseTag = getLatestPrereleaseTag(
7884
validTags,
@@ -218,7 +224,8 @@ export default async function main() {
218224
return;
219225
}
220226

221-
if (validTags.map((tag) => tag.name).includes(newTag)) {
227+
const tagExists = tags.map((tag) => tag.name).includes(newTag);
228+
if (tagExists && !forceUpdate) {
222229
core.info('This tag already exists. Skipping the tag creation.');
223230
return;
224231
}
@@ -228,5 +235,5 @@ export default async function main() {
228235
return;
229236
}
230237

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

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

+4-9
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,19 @@ 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>>;
107

118
export async function getValidTags(
12-
prefixRegex: RegExp,
13-
shouldFetchAllTags: boolean
9+
tags: Tags,
10+
prefixRegex: RegExp
1411
) {
15-
const tags = await listTags(shouldFetchAllTags);
16-
1712
const invalidTags = tags.filter(
1813
(tag) =>
1914
!prefixRegex.test(tag.name) || !valid(tag.name.replace(prefixRegex, ''))
2015
);
2116

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

2419
const validTags = tags
2520
.filter(

0 commit comments

Comments
 (0)