mirror of
https://github.com/softprops/action-gh-release.git
synced 2025-11-23 11:50:51 +00:00
feat: mark release as draft until all artifacts are uploaded
Previously, the releases were created and then artifacts (if any) were added to them. This broke when GitHub released "immutable" releases, which disallow changes after the release is published. Make it so that releases are always marked as "draft" when being worked on by the action, and unmarked as draft (if desired) once the action is completed. Fixes #653
This commit is contained in:
parent
5be0e66d93
commit
f0aaee5ca0
4 changed files with 67 additions and 8 deletions
|
|
@ -49,6 +49,7 @@ describe('github', () => {
|
||||||
getReleaseByTag: () => Promise.reject('Not implemented'),
|
getReleaseByTag: () => Promise.reject('Not implemented'),
|
||||||
createRelease: () => Promise.reject('Not implemented'),
|
createRelease: () => Promise.reject('Not implemented'),
|
||||||
updateRelease: () => Promise.reject('Not implemented'),
|
updateRelease: () => Promise.reject('Not implemented'),
|
||||||
|
finalizeRelease: () => Promise.reject('Not implemented'),
|
||||||
allReleases: async function* () {
|
allReleases: async function* () {
|
||||||
yield { data: [mockRelease] };
|
yield { data: [mockRelease] };
|
||||||
},
|
},
|
||||||
|
|
@ -254,11 +255,12 @@ describe('github', () => {
|
||||||
name: 'test',
|
name: 'test',
|
||||||
body: 'test',
|
body: 'test',
|
||||||
target_commitish: 'main',
|
target_commitish: 'main',
|
||||||
draft: false,
|
draft: true,
|
||||||
prerelease: false,
|
prerelease: false,
|
||||||
assets: [],
|
assets: [],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
finalizeRelease: async () => {},
|
||||||
allReleases: async function* () {
|
allReleases: async function* () {
|
||||||
yield {
|
yield {
|
||||||
data: [
|
data: [
|
||||||
|
|
|
||||||
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -58,6 +58,12 @@ export interface Releaser {
|
||||||
make_latest: 'true' | 'false' | 'legacy' | undefined;
|
make_latest: 'true' | 'false' | 'legacy' | undefined;
|
||||||
}): Promise<{ data: Release }>;
|
}): Promise<{ data: Release }>;
|
||||||
|
|
||||||
|
finalizeRelease(params: {
|
||||||
|
owner: string;
|
||||||
|
repo: string;
|
||||||
|
release_id: number;
|
||||||
|
}): Promise<{ data: Release }>;
|
||||||
|
|
||||||
allReleases(params: { owner: string; repo: string }): AsyncIterableIterator<{ data: Release[] }>;
|
allReleases(params: { owner: string; repo: string }): AsyncIterableIterator<{ data: Release[] }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,6 +166,15 @@ export class GitHubReleaser implements Releaser {
|
||||||
return this.github.rest.repos.updateRelease(params);
|
return this.github.rest.repos.updateRelease(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async finalizeRelease(params: { owner: string; repo: string; release_id: number }) {
|
||||||
|
return await this.github.rest.repos.updateRelease({
|
||||||
|
owner: params.owner,
|
||||||
|
repo: params.repo,
|
||||||
|
release_id: params.release_id,
|
||||||
|
draft: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
allReleases(params: { owner: string; repo: string }): AsyncIterableIterator<{ data: Release[] }> {
|
allReleases(params: { owner: string; repo: string }): AsyncIterableIterator<{ data: Release[] }> {
|
||||||
const updatedParams = { per_page: 100, ...params };
|
const updatedParams = { per_page: 100, ...params };
|
||||||
return this.github.paginate.iterator(
|
return this.github.paginate.iterator(
|
||||||
|
|
@ -303,7 +318,6 @@ export const release = async (
|
||||||
body = workflowBody || existingReleaseBody;
|
body = workflowBody || existingReleaseBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
const draft = config.input_draft !== undefined ? config.input_draft : existingRelease.draft;
|
|
||||||
const prerelease =
|
const prerelease =
|
||||||
config.input_prerelease !== undefined ? config.input_prerelease : existingRelease.prerelease;
|
config.input_prerelease !== undefined ? config.input_prerelease : existingRelease.prerelease;
|
||||||
|
|
||||||
|
|
@ -317,7 +331,7 @@ export const release = async (
|
||||||
target_commitish,
|
target_commitish,
|
||||||
name,
|
name,
|
||||||
body,
|
body,
|
||||||
draft,
|
draft: existingRelease.draft,
|
||||||
prerelease,
|
prerelease,
|
||||||
discussion_category_name,
|
discussion_category_name,
|
||||||
generate_release_notes,
|
generate_release_notes,
|
||||||
|
|
@ -345,6 +359,45 @@ export const release = async (
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizes a release by unmarking it as "draft" (if relevant)
|
||||||
|
* after all artifacts have been uploaded.
|
||||||
|
*
|
||||||
|
* @param config - Release configuration as specified by user
|
||||||
|
* @param releaser - The GitHub API wrapper for release operations
|
||||||
|
* @param release - The existing release to be finalized
|
||||||
|
* @param maxRetries - The maximum number of attempts to finalize the release
|
||||||
|
*/
|
||||||
|
export const finalizeRelease = async (
|
||||||
|
config: Config,
|
||||||
|
releaser: Releaser,
|
||||||
|
release: Release,
|
||||||
|
maxRetries: number = 3,
|
||||||
|
): Promise<Release> => {
|
||||||
|
if (config.input_draft === true) {
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxRetries <= 0) {
|
||||||
|
console.log(`❌ Too many retries. Aborting...`);
|
||||||
|
throw new Error('Too many retries.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const [owner, repo] = config.github_repository.split('/');
|
||||||
|
try {
|
||||||
|
const { data } = await releaser.finalizeRelease({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
release_id: release.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
} catch {
|
||||||
|
console.log(`retrying... (${maxRetries - 1} retries remaining)`);
|
||||||
|
return finalizeRelease(config, releaser, release, maxRetries - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a release by tag name from all a repository's releases.
|
* Finds a release by tag name from all a repository's releases.
|
||||||
*
|
*
|
||||||
|
|
@ -385,7 +438,6 @@ async function createRelease(
|
||||||
const tag_name = tag;
|
const tag_name = tag;
|
||||||
const name = config.input_name || tag;
|
const name = config.input_name || tag;
|
||||||
const body = releaseBody(config);
|
const body = releaseBody(config);
|
||||||
const draft = config.input_draft;
|
|
||||||
const prerelease = config.input_prerelease;
|
const prerelease = config.input_prerelease;
|
||||||
const target_commitish = config.input_target_commitish;
|
const target_commitish = config.input_target_commitish;
|
||||||
const make_latest = config.input_make_latest;
|
const make_latest = config.input_make_latest;
|
||||||
|
|
@ -401,7 +453,7 @@ async function createRelease(
|
||||||
tag_name,
|
tag_name,
|
||||||
name,
|
name,
|
||||||
body,
|
body,
|
||||||
draft,
|
draft: true,
|
||||||
prerelease,
|
prerelease,
|
||||||
target_commitish,
|
target_commitish,
|
||||||
discussion_category_name,
|
discussion_category_name,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { setFailed, setOutput } from '@actions/core';
|
import { setFailed, setOutput } from '@actions/core';
|
||||||
import { getOctokit } from '@actions/github';
|
import { getOctokit } from '@actions/github';
|
||||||
import { GitHubReleaser, release, upload } from './github';
|
import { GitHubReleaser, release, finalizeRelease, upload } from './github';
|
||||||
import { isTag, parseConfig, paths, unmatchedPatterns, uploadUrl } from './util';
|
import { isTag, parseConfig, paths, unmatchedPatterns, uploadUrl } from './util';
|
||||||
|
|
||||||
import { env } from 'process';
|
import { env } from 'process';
|
||||||
|
|
@ -48,7 +48,8 @@ async function run() {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
//);
|
//);
|
||||||
const rel = await release(config, new GitHubReleaser(gh));
|
const releaser = new GitHubReleaser(gh);
|
||||||
|
let rel = await release(config, releaser);
|
||||||
if (config.input_files && config.input_files.length > 0) {
|
if (config.input_files && config.input_files.length > 0) {
|
||||||
const files = paths(config.input_files, config.input_working_directory);
|
const files = paths(config.input_files, config.input_working_directory);
|
||||||
if (files.length == 0) {
|
if (files.length == 0) {
|
||||||
|
|
@ -81,6 +82,10 @@ async function run() {
|
||||||
const assets = results.filter(Boolean);
|
const assets = results.filter(Boolean);
|
||||||
setOutput('assets', assets);
|
setOutput('assets', assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Finalizing release...');
|
||||||
|
rel = await finalizeRelease(config, releaser, rel);
|
||||||
|
|
||||||
console.log(`🎉 Release ready at ${rel.html_url}`);
|
console.log(`🎉 Release ready at ${rel.html_url}`);
|
||||||
setOutput('url', rel.html_url);
|
setOutput('url', rel.html_url);
|
||||||
setOutput('id', rel.id.toString());
|
setOutput('id', rel.id.toString());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue