Skip to content

Commit 462b212

Browse files
committed
fix: draft prereleases before uploading assets
Signed-off-by: Rui Chen <rui@chenrui.dev>
1 parent 8a8510e commit 462b212

File tree

5 files changed

+58
-4
lines changed

5 files changed

+58
-4
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ will retain its original info.
240240
existing draft release, set `draft: true` to keep it draft; if `draft` is omitted,
241241
the action will publish that draft after uploading assets.
242242

243+
💡 When the action creates a new release that uploads assets, it stages the release
244+
as a draft first, uploads the assets, and then publishes it unless `draft: true`
245+
keeps it as a draft. This keeps new prereleases compatible with GitHub immutable
246+
releases.
247+
243248
💡 `files` is glob-based, so literal filenames that contain glob metacharacters such as
244249
`[` or `]` must be escaped in the pattern.
245250

__tests__/github.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ describe('github', () => {
517517
);
518518
});
519519

520-
it('creates published prereleases without the forced draft-first path', async () => {
520+
it('creates published prereleases without the forced draft-first path when no assets are configured', async () => {
521521
const prereleaseConfig = {
522522
...config,
523523
input_prerelease: true,
@@ -564,6 +564,54 @@ describe('github', () => {
564564
);
565565
});
566566

567+
it('creates draft prereleases when assets are configured so uploads can finish before publish', async () => {
568+
const prereleaseConfig = {
569+
...config,
570+
input_prerelease: true,
571+
input_draft: false,
572+
input_files: ['draft-false.txt'],
573+
};
574+
const createdRelease: Release = {
575+
id: 1,
576+
upload_url: 'test',
577+
html_url: 'test',
578+
tag_name: 'v1.0.0',
579+
name: 'test',
580+
body: 'test',
581+
target_commitish: 'main',
582+
draft: true,
583+
prerelease: true,
584+
assets: [],
585+
};
586+
587+
const createReleaseSpy = vi.fn(async () => ({ data: createdRelease }));
588+
const mockReleaser: Releaser = {
589+
getReleaseByTag: () => Promise.reject({ status: 404 }),
590+
createRelease: createReleaseSpy,
591+
updateRelease: () => Promise.reject('Not implemented'),
592+
finalizeRelease: () => Promise.reject('Not implemented'),
593+
allReleases: async function* () {
594+
yield { data: [createdRelease] };
595+
},
596+
listReleaseAssets: () => Promise.reject('Not implemented'),
597+
deleteReleaseAsset: () => Promise.reject('Not implemented'),
598+
deleteRelease: () => Promise.reject('Not implemented'),
599+
updateReleaseAsset: () => Promise.reject('Not implemented'),
600+
uploadReleaseAsset: () => Promise.reject('Not implemented'),
601+
} as const;
602+
603+
const result = await release(prereleaseConfig, mockReleaser, 1);
604+
605+
assert.equal(result.release.id, createdRelease.id);
606+
assert.equal(result.created, true);
607+
expect(createReleaseSpy).toHaveBeenCalledWith(
608+
expect.objectContaining({
609+
draft: true,
610+
prerelease: true,
611+
}),
612+
);
613+
});
614+
567615
it('retries upload after deleting conflicting asset on 422 already_exists race', async () => {
568616
const uploadReleaseAsset = vi
569617
.fn()

action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ inputs:
1616
description: "Gives a tag name. Defaults to github.ref_name. refs/tags/<name> values are normalized to <name>."
1717
required: false
1818
draft:
19-
description: "Keeps the release as a draft. Defaults to false. When reusing an existing draft release, set this to true to keep it draft; omit it to publish after upload."
19+
description: "Keeps the release as a draft. Defaults to false. New releases that upload assets are staged as drafts first; set this to true to keep the release draft instead of publishing it after upload."
2020
required: false
2121
prerelease:
2222
description: "Identify the release as a prerelease. Defaults to false"

0 commit comments

Comments
 (0)