Skip to content

Commit 1b125c1

Browse files
committed
Support deleting existing releases
Extracted from softprops#181
1 parent 44946dc commit 1b125c1

File tree

6 files changed

+117
-50
lines changed

6 files changed

+117
-50
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ The following are optional as `step.with` keys
180180
| `token` | String | Secret GitHub Personal Access Token. Defaults to `${{ github.token }}` |
181181
| `discussion_category_name` | String | If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see ["Managing categories for discussions in your repository."](https://docs.github.com/en/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository) |
182182
| `generate_release_notes` | Boolean | Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes. See the [GitHub docs for this feature](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) for more information |
183+
| `delete_on_existing` | Boolean | Whether or not to delete an existing release entirely when running this action. |
183184

184185
💡 When providing a `body` and `body_path` at the same time, `body_path` will be
185186
attempted first, then falling back on `body` if the path can not be read from.

__tests__/util.test.ts

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ describe("util", () => {
5151
input_tag_name: undefined,
5252
input_target_commitish: undefined,
5353
input_discussion_category_name: undefined,
54-
input_generate_release_notes: false
54+
input_generate_release_notes: false,
55+
input_delete_on_existing: false
5556
})
5657
);
5758
});
@@ -71,7 +72,8 @@ describe("util", () => {
7172
input_tag_name: undefined,
7273
input_target_commitish: undefined,
7374
input_discussion_category_name: undefined,
74-
input_generate_release_notes: false
75+
input_generate_release_notes: false,
76+
input_delete_on_existing: false
7577
})
7678
);
7779
});
@@ -91,7 +93,8 @@ describe("util", () => {
9193
input_tag_name: undefined,
9294
input_target_commitish: undefined,
9395
input_discussion_category_name: undefined,
94-
input_generate_release_notes: false
96+
input_generate_release_notes: false,
97+
input_delete_on_existing: false
9598
})
9699
);
97100
});
@@ -123,7 +126,8 @@ describe("util", () => {
123126
input_fail_on_unmatched_files: false,
124127
input_target_commitish: undefined,
125128
input_discussion_category_name: undefined,
126-
input_generate_release_notes: false
129+
input_generate_release_notes: false,
130+
input_delete_on_existing: false
127131
}
128132
);
129133
});
@@ -147,7 +151,8 @@ describe("util", () => {
147151
input_fail_on_unmatched_files: false,
148152
input_target_commitish: "affa18ef97bc9db20076945705aba8c516139abd",
149153
input_discussion_category_name: undefined,
150-
input_generate_release_notes: false
154+
input_generate_release_notes: false,
155+
input_delete_on_existing: false
151156
}
152157
);
153158
});
@@ -170,7 +175,8 @@ describe("util", () => {
170175
input_fail_on_unmatched_files: false,
171176
input_target_commitish: undefined,
172177
input_discussion_category_name: "releases",
173-
input_generate_release_notes: false
178+
input_generate_release_notes: false,
179+
input_delete_on_existing: false
174180
}
175181
);
176182
});
@@ -194,7 +200,33 @@ describe("util", () => {
194200
input_fail_on_unmatched_files: false,
195201
input_target_commitish: undefined,
196202
input_discussion_category_name: undefined,
197-
input_generate_release_notes: true
203+
input_generate_release_notes: true,
204+
input_delete_on_existing: false
205+
}
206+
);
207+
});
208+
209+
it("supports deleting existing releases", () => {
210+
assert.deepStrictEqual(
211+
parseConfig({
212+
INPUT_DELETE_ON_EXISTING: "true"
213+
}),
214+
{
215+
github_ref: "",
216+
github_repository: "",
217+
github_token: "",
218+
input_body: undefined,
219+
input_body_path: undefined,
220+
input_draft: undefined,
221+
input_prerelease: undefined,
222+
input_files: [],
223+
input_name: undefined,
224+
input_tag_name: undefined,
225+
input_fail_on_unmatched_files: false,
226+
input_target_commitish: undefined,
227+
input_discussion_category_name: undefined,
228+
input_generate_release_notes: false,
229+
input_delete_on_existing: true
198230
}
199231
);
200232
});
@@ -221,7 +253,8 @@ describe("util", () => {
221253
input_fail_on_unmatched_files: false,
222254
input_target_commitish: undefined,
223255
input_discussion_category_name: undefined,
224-
input_generate_release_notes: false
256+
input_generate_release_notes: false,
257+
input_delete_on_existing: false
225258
}
226259
);
227260
});
@@ -246,7 +279,8 @@ describe("util", () => {
246279
input_fail_on_unmatched_files: false,
247280
input_target_commitish: undefined,
248281
input_discussion_category_name: undefined,
249-
input_generate_release_notes: false
282+
input_generate_release_notes: false,
283+
input_delete_on_existing: false
250284
}
251285
);
252286
});
@@ -270,7 +304,8 @@ describe("util", () => {
270304
input_fail_on_unmatched_files: false,
271305
input_target_commitish: undefined,
272306
input_discussion_category_name: undefined,
273-
input_generate_release_notes: false
307+
input_generate_release_notes: false,
308+
input_delete_on_existing: false
274309
}
275310
);
276311
});

action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ inputs:
4343
generate_release_notes:
4444
description: "Whether to automatically generate the name and body for this release. If name is specified, the specified name will be used; otherwise, a name will be automatically generated. If body is specified, the body will be pre-pended to the automatically generated notes."
4545
required: false
46+
delete_on_existing:
47+
description: "Whether or not to delete an existing release entirely when running this action."
48+
required: false
4649
env:
4750
"GITHUB_TOKEN": "As provided by Github Actions"
4851
outputs:

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/github.ts

Lines changed: 64 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ export interface Releaser {
6161
generate_release_notes: boolean | undefined;
6262
}): Promise<{ data: Release }>;
6363

64+
deleteRelease(params: {
65+
owner: string;
66+
repo: string;
67+
release_id: number;
68+
}): Promise<{ data: Release }>;
69+
6470
allReleases(params: {
6571
owner: string;
6672
repo: string;
@@ -112,6 +118,14 @@ export class GitHubReleaser implements Releaser {
112118
return this.github.rest.repos.updateRelease(params);
113119
}
114120

121+
deleteRelease(params: {
122+
owner: string;
123+
repo: string;
124+
release_id: number;
125+
}): Promise<{ data: Release }> {
126+
return this.github.rest.repos.deleteRelease(params);
127+
}
128+
115129
allReleases(params: {
116130
owner: string;
117131
repo: string;
@@ -198,6 +212,48 @@ export const release = async (
198212

199213
const discussion_category_name = config.input_discussion_category_name;
200214
const generate_release_notes = config.input_generate_release_notes;
215+
216+
const createRelease = async () => {
217+
const tag_name = tag;
218+
const name = config.input_name || tag;
219+
const body = releaseBody(config);
220+
const draft = config.input_draft;
221+
const prerelease = config.input_prerelease;
222+
const target_commitish = config.input_target_commitish;
223+
let commitMessage: string = "";
224+
if (target_commitish) {
225+
commitMessage = ` using commit "${target_commitish}"`;
226+
}
227+
console.log(
228+
`👩‍🏭 Creating new GitHub release for tag ${tag_name}${commitMessage}...`
229+
);
230+
try {
231+
let release = await releaser.createRelease({
232+
owner,
233+
repo,
234+
tag_name,
235+
name,
236+
body,
237+
draft,
238+
prerelease,
239+
target_commitish,
240+
discussion_category_name,
241+
generate_release_notes
242+
});
243+
return release.data;
244+
} catch (error) {
245+
// presume a race with competing metrix runs
246+
console.log(
247+
`⚠️ GitHub release failed with status: ${
248+
error.status
249+
}\n${JSON.stringify(
250+
error.response.data.errors
251+
)}\nretrying... (${maxRetries - 1} retries remaining)`
252+
);
253+
return release(config, releaser, maxRetries - 1);
254+
}
255+
};
256+
201257
try {
202258
// you can't get a an existing draft by tag
203259
// so we must find one in the list of all releases
@@ -219,6 +275,13 @@ export const release = async (
219275
});
220276

221277
const release_id = existingRelease.data.id;
278+
279+
if (config.input_delete_on_existing) {
280+
console.log(`⚠ Deleting existing release ${owner}/${repo}@${release_id}`);
281+
await releaser.deleteRelease({ owner, repo, release_id });
282+
return createRelease();
283+
}
284+
222285
let target_commitish: string;
223286
if (
224287
config.input_target_commitish &&
@@ -265,44 +328,7 @@ export const release = async (
265328
return release.data;
266329
} catch (error) {
267330
if (error.status === 404) {
268-
const tag_name = tag;
269-
const name = config.input_name || tag;
270-
const body = releaseBody(config);
271-
const draft = config.input_draft;
272-
const prerelease = config.input_prerelease;
273-
const target_commitish = config.input_target_commitish;
274-
let commitMessage: string = "";
275-
if (target_commitish) {
276-
commitMessage = ` using commit "${target_commitish}"`;
277-
}
278-
console.log(
279-
`👩‍🏭 Creating new GitHub release for tag ${tag_name}${commitMessage}...`
280-
);
281-
try {
282-
let release = await releaser.createRelease({
283-
owner,
284-
repo,
285-
tag_name,
286-
name,
287-
body,
288-
draft,
289-
prerelease,
290-
target_commitish,
291-
discussion_category_name,
292-
generate_release_notes
293-
});
294-
return release.data;
295-
} catch (error) {
296-
// presume a race with competing metrix runs
297-
console.log(
298-
`⚠️ GitHub release failed with status: ${
299-
error.status
300-
}\n${JSON.stringify(
301-
error.response.data.errors
302-
)}\nretrying... (${maxRetries - 1} retries remaining)`
303-
);
304-
return release(config, releaser, maxRetries - 1);
305-
}
331+
return createRelease();
306332
} else {
307333
console.log(
308334
`⚠️ Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`

src/util.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface Config {
1818
input_target_commitish?: string;
1919
input_discussion_category_name?: string;
2020
input_generate_release_notes?: boolean;
21+
input_delete_on_existing?: boolean;
2122
}
2223

2324
export const uploadUrl = (url: string): string => {
@@ -67,7 +68,8 @@ export const parseConfig = (env: Env): Config => {
6768
input_target_commitish: env.INPUT_TARGET_COMMITISH || undefined,
6869
input_discussion_category_name:
6970
env.INPUT_DISCUSSION_CATEGORY_NAME || undefined,
70-
input_generate_release_notes: env.INPUT_GENERATE_RELEASE_NOTES == "true"
71+
input_generate_release_notes: env.INPUT_GENERATE_RELEASE_NOTES == "true",
72+
input_delete_on_existing: env.INPUT_DELETE_ON_EXISTING == "true"
7173
};
7274
};
7375

0 commit comments

Comments
 (0)