@@ -25,6 +25,7 @@ This action will create a GitHub release and optionally upload an artifact to it
|
||||
| discussionCategory | When provided this will generate a discussion of the specified category. The category must exist otherwise this will cause the action to fail. This isn't used with draft releases. The default "Announcements" category is not supported via the API and will cause an error if used here. | false | "" |
|
||||
| draft | Optionally marks this release as a draft release. Set to true to enable. | false | "" |
|
||||
| generateReleaseNotes | Indicates if release notes should be automatically generated. | false | false |
|
||||
| immutableCreate | Indicates if immutable release creation should be used. When enabled, the action will first create a draft, upload artifacts, then publish the release. | false | true |
|
||||
| makeLatest | Indicates if the release should be the "latest" release or not. legacy specifies that the latest release should be determined based on the release creation date and higher semantic version. | false | "legacy" |
|
||||
| name | An optional name for the release. If this is omitted the tag will be used. | false | "" |
|
||||
| omitBody | Indicates if the release body should be omitted. | false | false |
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
| discussionCategory | 当提供该选项时,将生成指定类别的 discussion。指定的类别必须存在,否则将导致 Action 失败。这对草案状态的发布不生效。API 不支持默认的 Announcement 分类,使用这个分类会引发错误。 | false | "" |
|
||||
| draft | 可选择将此版本标记为草稿版本。 设置为 true 以启用。 | false | "" |
|
||||
| generateReleaseNotes | 指示是否应自动生成发行说明。 | false | false |
|
||||
| immutableCreate | 指示是否应使用不可变发布创建。启用时,操作将首先创建草稿,上传产出文件,然后发布版本。 | false | true |
|
||||
| makeLatest | 指示是否将这个发布设置为 latest。使用"lagecy"值则会根据发布时间和语义化版本号自动决定。 | false | "legacy" |
|
||||
| name | 版本的可选名称。 如果省略,将使用标签。 | false | "" |
|
||||
| omitBody | 指示是否应省略发布主体。 | false | false |
|
||||
|
||||
@@ -529,6 +529,145 @@ describe("Action", () => {
|
||||
})
|
||||
})
|
||||
|
||||
it("does not publish immutable release when immutableCreate is false", async () => {
|
||||
const action = createAction(false, true, false, true, false, createBody, false, false)
|
||||
|
||||
await action.perform()
|
||||
|
||||
expect(createMock).toHaveBeenCalledWith(
|
||||
tag,
|
||||
generatedReleaseBody,
|
||||
commit,
|
||||
discussionCategory,
|
||||
false, // draft should be false when createdDraft is false
|
||||
makeLatest,
|
||||
createName,
|
||||
createPrerelease
|
||||
)
|
||||
// Should only call update once for regular create, not for publishImmutableRelease
|
||||
expect(updateMock).not.toHaveBeenCalled()
|
||||
assertOutputApplied()
|
||||
})
|
||||
|
||||
it("does not publish immutable release when createdDraft is true", async () => {
|
||||
const action = createAction(false, true, false, true, false, createBody, true, true)
|
||||
|
||||
await action.perform()
|
||||
|
||||
expect(createMock).toHaveBeenCalledWith(
|
||||
tag,
|
||||
generatedReleaseBody,
|
||||
commit,
|
||||
discussionCategory,
|
||||
true, // draft should be true when createdDraft is true or immutableCreate is true
|
||||
makeLatest,
|
||||
createName,
|
||||
createPrerelease
|
||||
)
|
||||
// Should only call update once for regular create, not for publishImmutableRelease
|
||||
expect(updateMock).not.toHaveBeenCalled()
|
||||
assertOutputApplied()
|
||||
})
|
||||
|
||||
it("publishes immutable release when immutableCreate is true and createdDraft is false", async () => {
|
||||
const action = createAction(false, true, false, true, false, createBody, true, false)
|
||||
const immutableReleaseResponse = {
|
||||
data: {
|
||||
id: 999,
|
||||
upload_url: "http://immutable.example.com",
|
||||
html_url: "https://github.com/owner/repo/releases/tag/v1.0.0-immutable",
|
||||
tarball_url: "https://api.github.com/repos/owner/repo/tarball/v1.0.0-immutable",
|
||||
zipball_url: "https://api.github.com/repos/owner/repo/zipball/v1.0.0-immutable",
|
||||
},
|
||||
}
|
||||
updateMock.mockResolvedValueOnce(immutableReleaseResponse)
|
||||
|
||||
await action.perform()
|
||||
|
||||
expect(createMock).toHaveBeenCalledWith(
|
||||
tag,
|
||||
generatedReleaseBody,
|
||||
commit,
|
||||
discussionCategory,
|
||||
true, // draft should be true when immutableCreate is true
|
||||
makeLatest,
|
||||
createName,
|
||||
createPrerelease
|
||||
)
|
||||
// Should call update for publishImmutableRelease
|
||||
expect(updateMock).toHaveBeenCalledWith(
|
||||
releaseId,
|
||||
tag,
|
||||
undefined, // body is omitted
|
||||
undefined, // commit is omitted
|
||||
discussionCategory,
|
||||
false, // draft is set to false to publish the release
|
||||
makeLatest,
|
||||
createName,
|
||||
createPrerelease
|
||||
)
|
||||
// Should apply the immutable release data instead of the original
|
||||
expect(applyReleaseDataMock).toHaveBeenCalledWith(immutableReleaseResponse.data)
|
||||
assertAssetUrlsApplied({
|
||||
"art1": "https://github.com/owner/repo/releases/download/v1.0.0/art1",
|
||||
"art2": "https://github.com/owner/repo/releases/download/v1.0.0/art2",
|
||||
})
|
||||
})
|
||||
|
||||
it("publishes immutable release when allowUpdates is true but release does not exist", async () => {
|
||||
const action = createAction(true, true, false, true, false, createBody, true, false)
|
||||
const error = { status: 404 }
|
||||
getMock.mockRejectedValue(error)
|
||||
listMock.mockResolvedValue({ data: [] }) // No draft releases found
|
||||
|
||||
const immutableReleaseResponse = {
|
||||
data: {
|
||||
id: 888,
|
||||
upload_url: "http://immutable-update.example.com",
|
||||
html_url: "https://github.com/owner/repo/releases/tag/v1.0.0-immutable-update",
|
||||
tarball_url: "https://api.github.com/repos/owner/repo/tarball/v1.0.0-immutable-update",
|
||||
zipball_url: "https://api.github.com/repos/owner/repo/zipball/v1.0.0-immutable-update",
|
||||
},
|
||||
}
|
||||
updateMock.mockResolvedValueOnce(immutableReleaseResponse)
|
||||
|
||||
await action.perform()
|
||||
|
||||
// Should try to get the release first (allowUpdates=true)
|
||||
expect(getMock).toHaveBeenCalledWith(tag)
|
||||
// Should check for draft releases when get fails with 404
|
||||
expect(listMock).toHaveBeenCalled()
|
||||
// Should create a new release when no drafts found
|
||||
expect(createMock).toHaveBeenCalledWith(
|
||||
tag,
|
||||
generatedReleaseBody,
|
||||
commit,
|
||||
discussionCategory,
|
||||
true, // draft should be true when immutableCreate is true
|
||||
makeLatest,
|
||||
createName,
|
||||
createPrerelease
|
||||
)
|
||||
// Should call update for publishImmutableRelease
|
||||
expect(updateMock).toHaveBeenCalledWith(
|
||||
releaseId,
|
||||
tag,
|
||||
undefined, // body is omitted
|
||||
undefined, // commit is omitted
|
||||
discussionCategory,
|
||||
false, // draft is set to false to publish the release
|
||||
makeLatest,
|
||||
createName,
|
||||
createPrerelease
|
||||
)
|
||||
// Should apply the immutable release data instead of the original
|
||||
expect(applyReleaseDataMock).toHaveBeenCalledWith(immutableReleaseResponse.data)
|
||||
assertAssetUrlsApplied({
|
||||
"art1": "https://github.com/owner/repo/releases/download/v1.0.0/art1",
|
||||
"art2": "https://github.com/owner/repo/releases/download/v1.0.0/art2",
|
||||
})
|
||||
})
|
||||
|
||||
function assertOutputApplied() {
|
||||
expect(applyReleaseDataMock).toHaveBeenCalledWith({
|
||||
id: releaseId,
|
||||
@@ -549,7 +688,9 @@ describe("Action", () => {
|
||||
removeArtifacts = false,
|
||||
generateReleaseNotes = true,
|
||||
omitBodyDuringUpdate = false,
|
||||
createdReleaseBody = createBody
|
||||
createdReleaseBody = createBody,
|
||||
immutableCreate = true,
|
||||
createdDraft = createDraft
|
||||
): Action {
|
||||
let inputArtifact: Artifact[]
|
||||
|
||||
@@ -615,12 +756,13 @@ describe("Action", () => {
|
||||
allowUpdates,
|
||||
artifactErrorsFailBuild: true,
|
||||
artifacts: inputArtifact,
|
||||
createdDraft: createDraft,
|
||||
createdDraft: createdDraft,
|
||||
createdReleaseBody: createdReleaseBody,
|
||||
createdReleaseName: createName,
|
||||
commit,
|
||||
discussionCategory,
|
||||
generateReleaseNotes,
|
||||
immutableCreate: immutableCreate,
|
||||
makeLatest: makeLatest,
|
||||
owner: "owner",
|
||||
createdPrerelease: createPrerelease,
|
||||
|
||||
@@ -200,6 +200,23 @@ describe("Inputs", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("immutableCreate", () => {
|
||||
it("returns true by default", function () {
|
||||
mockGetInput.mockReturnValue("")
|
||||
expect(inputs.immutableCreate).toBe(true)
|
||||
})
|
||||
|
||||
it("returns true when explicitly set", function () {
|
||||
mockGetInput.mockReturnValue("true")
|
||||
expect(inputs.immutableCreate).toBe(true)
|
||||
})
|
||||
|
||||
it("returns false when explicitly disabled", function () {
|
||||
mockGetInput.mockReturnValue("false")
|
||||
expect(inputs.immutableCreate).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("makeLatest", () => {
|
||||
it("returns legacy", () => {
|
||||
mockGetInput.mockReturnValueOnce("legacy")
|
||||
|
||||
@@ -45,6 +45,7 @@ describe.skip("Integration Test", () => {
|
||||
commit: undefined,
|
||||
discussionCategory: "Release",
|
||||
generateReleaseNotes: true,
|
||||
immutableCreate: true,
|
||||
omitBodyDuringUpdate: false,
|
||||
owner: "ncipollo",
|
||||
createdPrerelease: false,
|
||||
|
||||
@@ -47,6 +47,10 @@ inputs:
|
||||
description: 'Indicates if release notes should be automatically generated.'
|
||||
required: false
|
||||
default: 'false'
|
||||
immutableCreate:
|
||||
description: 'Indicates if immutable release creation should be used. When enabled, the action will first create a draft, upload artifacts, then publish the release.'
|
||||
required: false
|
||||
default: 'true'
|
||||
makeLatest:
|
||||
description: 'Indicates if the release should be the "latest" release or not.'
|
||||
required: false
|
||||
|
||||
89
dist/index.js
vendored
89
dist/index.js
vendored
@@ -66,20 +66,7 @@ class Action {
|
||||
core.notice("Skipping action, release already exists and skipIfReleaseExists is enabled.");
|
||||
return;
|
||||
}
|
||||
const releaseResponse = await this.createOrUpdateRelease();
|
||||
const releaseData = releaseResponse.data;
|
||||
const releaseId = releaseData.id;
|
||||
const uploadUrl = releaseData.upload_url;
|
||||
if (this.inputs.removeArtifacts) {
|
||||
await this.artifactDestroyer.destroyArtifacts(releaseId);
|
||||
}
|
||||
const artifacts = this.inputs.artifacts;
|
||||
let assetUrls = {};
|
||||
if (artifacts.length > 0) {
|
||||
assetUrls = await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl);
|
||||
}
|
||||
this.outputs.applyReleaseData(releaseData);
|
||||
this.outputs.applyAssetUrls(assetUrls);
|
||||
await this.createOrUpdateRelease();
|
||||
}
|
||||
async createOrUpdateRelease() {
|
||||
if (this.inputs.allowUpdates) {
|
||||
@@ -88,32 +75,25 @@ class Action {
|
||||
getResponse = await this.releases.getByTag(this.inputs.tag);
|
||||
}
|
||||
catch (error) {
|
||||
return await this.checkForMissingReleaseError(error);
|
||||
await this.checkForMissingReleaseError(error);
|
||||
return;
|
||||
}
|
||||
// Fail if this isn't an unreleased release & updateOnlyUnreleased is enabled.
|
||||
this.releaseValidator.validateReleaseUpdate(getResponse.data);
|
||||
return await this.updateRelease(getResponse.data.id);
|
||||
await this.updateRelease(getResponse.data.id);
|
||||
}
|
||||
else {
|
||||
return await this.createRelease();
|
||||
await this.createRelease();
|
||||
}
|
||||
}
|
||||
async checkForMissingReleaseError(error) {
|
||||
if (Action.noPublishedRelease(error)) {
|
||||
return await this.updateDraftOrCreateRelease();
|
||||
await this.updateDraftOrCreateRelease();
|
||||
}
|
||||
else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
async updateRelease(id) {
|
||||
let releaseBody = this.inputs.updatedReleaseBody;
|
||||
if (this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate) {
|
||||
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
|
||||
releaseBody = response.data.body;
|
||||
}
|
||||
return await this.releases.update(id, this.inputs.tag, releaseBody, this.inputs.commit, this.inputs.discussionCategory, this.inputs.updatedDraft, this.inputs.makeLatest, this.inputs.updatedReleaseName, this.inputs.updatedPrerelease);
|
||||
}
|
||||
static noPublishedRelease(error) {
|
||||
const githubError = new GithubError_1.GithubError(error);
|
||||
return githubError.status == 404;
|
||||
@@ -121,10 +101,10 @@ class Action {
|
||||
async updateDraftOrCreateRelease() {
|
||||
const draftReleaseId = await this.findMatchingDraftReleaseId();
|
||||
if (draftReleaseId) {
|
||||
return await this.updateRelease(draftReleaseId);
|
||||
await this.updateRelease(draftReleaseId);
|
||||
}
|
||||
else {
|
||||
return await this.createRelease();
|
||||
await this.createRelease();
|
||||
}
|
||||
}
|
||||
async findMatchingDraftReleaseId() {
|
||||
@@ -137,13 +117,60 @@ class Action {
|
||||
const draftRelease = releases.find((release) => release.draft && release.tag_name == tag);
|
||||
return draftRelease?.id;
|
||||
}
|
||||
async updateRelease(id) {
|
||||
let releaseBody = this.inputs.updatedReleaseBody;
|
||||
if (this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate) {
|
||||
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
|
||||
releaseBody = response.data.body;
|
||||
}
|
||||
const releaseResponse = await this.releases.update(id, this.inputs.tag, releaseBody, this.inputs.commit, this.inputs.discussionCategory, this.inputs.updatedDraft, this.inputs.makeLatest, this.inputs.updatedReleaseName, this.inputs.updatedPrerelease);
|
||||
await this.processReleaseArtifactsAndOutputs(releaseResponse, false);
|
||||
}
|
||||
async createRelease() {
|
||||
let releaseBody = this.inputs.createdReleaseBody;
|
||||
if (this.inputs.generateReleaseNotes) {
|
||||
const response = await this.releases.generateReleaseNotes(this.inputs.tag);
|
||||
releaseBody = response.data.body;
|
||||
}
|
||||
return await this.releases.create(this.inputs.tag, releaseBody, this.inputs.commit, this.inputs.discussionCategory, this.inputs.createdDraft, this.inputs.makeLatest, this.inputs.createdReleaseName, this.inputs.createdPrerelease);
|
||||
// If immutableCreate is enabled we need to start with a draft release
|
||||
const draft = this.inputs.createdDraft || this.inputs.immutableCreate;
|
||||
const releaseResponse = await this.releases.create(this.inputs.tag, releaseBody, this.inputs.commit, this.inputs.discussionCategory, draft, this.inputs.makeLatest, this.inputs.createdReleaseName, this.inputs.createdPrerelease);
|
||||
await this.processReleaseArtifactsAndOutputs(releaseResponse, true);
|
||||
}
|
||||
async processReleaseArtifactsAndOutputs(releaseResponse, wasCreated) {
|
||||
const releaseData = releaseResponse.data;
|
||||
const releaseId = releaseData.id;
|
||||
const uploadUrl = releaseData.upload_url;
|
||||
if (this.inputs.removeArtifacts) {
|
||||
await this.artifactDestroyer.destroyArtifacts(releaseId);
|
||||
}
|
||||
const artifacts = this.inputs.artifacts;
|
||||
let assetUrls = {};
|
||||
if (artifacts.length > 0) {
|
||||
assetUrls = await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl);
|
||||
}
|
||||
if (wasCreated) {
|
||||
const immutableRelease = await this.publishImmutableRelease(releaseId);
|
||||
if (immutableRelease) {
|
||||
this.setOutputs(immutableRelease.data, assetUrls);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.setOutputs(releaseData, assetUrls);
|
||||
}
|
||||
async publishImmutableRelease(releaseId) {
|
||||
// Check if immutableCreate is on and createdDraft is off
|
||||
if (!this.inputs.immutableCreate || this.inputs.createdDraft) {
|
||||
return undefined;
|
||||
}
|
||||
return await this.releases.update(releaseId, this.inputs.tag, undefined, // body is omitted
|
||||
undefined, // commit is omitted
|
||||
this.inputs.discussionCategory, false, // We want to publish the release, set draft to false
|
||||
this.inputs.makeLatest, this.inputs.createdReleaseName, this.inputs.createdPrerelease);
|
||||
}
|
||||
setOutputs(releaseData, assetUrls) {
|
||||
this.outputs.applyReleaseData(releaseData);
|
||||
this.outputs.applyAssetUrls(assetUrls);
|
||||
}
|
||||
}
|
||||
exports.Action = Action;
|
||||
@@ -833,6 +860,10 @@ class CoreInputs {
|
||||
const generate = core.getInput("generateReleaseNotes");
|
||||
return generate == "true";
|
||||
}
|
||||
get immutableCreate() {
|
||||
const immutable = core.getInput("immutableCreate");
|
||||
return immutable != "false";
|
||||
}
|
||||
get makeLatest() {
|
||||
let latest = core.getInput("makeLatest");
|
||||
if (latest == "true" || latest == "false" || latest == "legacy") {
|
||||
|
||||
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -41,7 +41,9 @@
|
||||
"testMatch": ["**/*.test.ts"],
|
||||
"testRunner": "jest-circus/runner",
|
||||
"transform": {
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
"^.+\\.ts$": ["ts-jest", {
|
||||
"tsconfig": "tsconfig.test.json"
|
||||
}]
|
||||
},
|
||||
"verbose": true
|
||||
},
|
||||
|
||||
142
src/Action.ts
142
src/Action.ts
@@ -47,83 +47,47 @@ export class Action {
|
||||
return
|
||||
}
|
||||
|
||||
const releaseResponse = await this.createOrUpdateRelease()
|
||||
const releaseData = releaseResponse.data
|
||||
const releaseId = releaseData.id
|
||||
const uploadUrl = releaseData.upload_url
|
||||
|
||||
if (this.inputs.removeArtifacts) {
|
||||
await this.artifactDestroyer.destroyArtifacts(releaseId)
|
||||
await this.createOrUpdateRelease()
|
||||
}
|
||||
|
||||
const artifacts = this.inputs.artifacts
|
||||
let assetUrls: Record<string, string> = {}
|
||||
if (artifacts.length > 0) {
|
||||
assetUrls = await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl)
|
||||
}
|
||||
|
||||
this.outputs.applyReleaseData(releaseData)
|
||||
this.outputs.applyAssetUrls(assetUrls)
|
||||
}
|
||||
|
||||
private async createOrUpdateRelease(): Promise<CreateOrUpdateReleaseResponse> {
|
||||
private async createOrUpdateRelease() {
|
||||
if (this.inputs.allowUpdates) {
|
||||
let getResponse: ReleaseByTagResponse
|
||||
try {
|
||||
getResponse = await this.releases.getByTag(this.inputs.tag)
|
||||
} catch (error: any) {
|
||||
return await this.checkForMissingReleaseError(error)
|
||||
await this.checkForMissingReleaseError(error)
|
||||
return
|
||||
}
|
||||
|
||||
// Fail if this isn't an unreleased release & updateOnlyUnreleased is enabled.
|
||||
this.releaseValidator.validateReleaseUpdate(getResponse.data)
|
||||
|
||||
return await this.updateRelease(getResponse.data.id)
|
||||
await this.updateRelease(getResponse.data.id)
|
||||
} else {
|
||||
return await this.createRelease()
|
||||
await this.createRelease()
|
||||
}
|
||||
}
|
||||
|
||||
private async checkForMissingReleaseError(error: Error): Promise<CreateOrUpdateReleaseResponse> {
|
||||
private async checkForMissingReleaseError(error: Error): Promise<void> {
|
||||
if (Action.noPublishedRelease(error)) {
|
||||
return await this.updateDraftOrCreateRelease()
|
||||
await this.updateDraftOrCreateRelease()
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private async updateRelease(id: number): Promise<UpdateReleaseResponse> {
|
||||
let releaseBody = this.inputs.updatedReleaseBody
|
||||
|
||||
if (this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate) {
|
||||
const response = await this.releases.generateReleaseNotes(this.inputs.tag)
|
||||
releaseBody = response.data.body
|
||||
}
|
||||
|
||||
return await this.releases.update(
|
||||
id,
|
||||
this.inputs.tag,
|
||||
releaseBody,
|
||||
this.inputs.commit,
|
||||
this.inputs.discussionCategory,
|
||||
this.inputs.updatedDraft,
|
||||
this.inputs.makeLatest,
|
||||
this.inputs.updatedReleaseName,
|
||||
this.inputs.updatedPrerelease
|
||||
)
|
||||
}
|
||||
|
||||
private static noPublishedRelease(error: any): boolean {
|
||||
const githubError = new GithubError(error)
|
||||
return githubError.status == 404
|
||||
}
|
||||
|
||||
private async updateDraftOrCreateRelease(): Promise<CreateReleaseResponse | UpdateReleaseResponse> {
|
||||
private async updateDraftOrCreateRelease(): Promise<void> {
|
||||
const draftReleaseId = await this.findMatchingDraftReleaseId()
|
||||
if (draftReleaseId) {
|
||||
return await this.updateRelease(draftReleaseId)
|
||||
await this.updateRelease(draftReleaseId)
|
||||
} else {
|
||||
return await this.createRelease()
|
||||
await this.createRelease()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +104,30 @@ export class Action {
|
||||
return draftRelease?.id
|
||||
}
|
||||
|
||||
private async createRelease(): Promise<CreateReleaseResponse> {
|
||||
private async updateRelease(id: number) {
|
||||
let releaseBody = this.inputs.updatedReleaseBody
|
||||
|
||||
if (this.inputs.generateReleaseNotes && !this.inputs.omitBodyDuringUpdate) {
|
||||
const response = await this.releases.generateReleaseNotes(this.inputs.tag)
|
||||
releaseBody = response.data.body
|
||||
}
|
||||
|
||||
const releaseResponse = await this.releases.update(
|
||||
id,
|
||||
this.inputs.tag,
|
||||
releaseBody,
|
||||
this.inputs.commit,
|
||||
this.inputs.discussionCategory,
|
||||
this.inputs.updatedDraft,
|
||||
this.inputs.makeLatest,
|
||||
this.inputs.updatedReleaseName,
|
||||
this.inputs.updatedPrerelease
|
||||
)
|
||||
|
||||
await this.processReleaseArtifactsAndOutputs(releaseResponse, false)
|
||||
}
|
||||
|
||||
private async createRelease() {
|
||||
let releaseBody = this.inputs.createdReleaseBody
|
||||
|
||||
if (this.inputs.generateReleaseNotes) {
|
||||
@@ -148,15 +135,70 @@ export class Action {
|
||||
releaseBody = response.data.body
|
||||
}
|
||||
|
||||
return await this.releases.create(
|
||||
// If immutableCreate is enabled we need to start with a draft release
|
||||
const draft = this.inputs.createdDraft || this.inputs.immutableCreate
|
||||
|
||||
const releaseResponse = await this.releases.create(
|
||||
this.inputs.tag,
|
||||
releaseBody,
|
||||
this.inputs.commit,
|
||||
this.inputs.discussionCategory,
|
||||
this.inputs.createdDraft,
|
||||
draft,
|
||||
this.inputs.makeLatest,
|
||||
this.inputs.createdReleaseName,
|
||||
this.inputs.createdPrerelease
|
||||
)
|
||||
|
||||
await this.processReleaseArtifactsAndOutputs(releaseResponse, true)
|
||||
}
|
||||
|
||||
private async processReleaseArtifactsAndOutputs(releaseResponse: CreateOrUpdateReleaseResponse, wasCreated: boolean) {
|
||||
const releaseData = releaseResponse.data
|
||||
const releaseId = releaseData.id
|
||||
const uploadUrl = releaseData.upload_url
|
||||
|
||||
if (this.inputs.removeArtifacts) {
|
||||
await this.artifactDestroyer.destroyArtifacts(releaseId)
|
||||
}
|
||||
|
||||
const artifacts = this.inputs.artifacts
|
||||
let assetUrls: Record<string, string> = {}
|
||||
if (artifacts.length > 0) {
|
||||
assetUrls = await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl)
|
||||
}
|
||||
|
||||
if (wasCreated) {
|
||||
const immutableRelease = await this.publishImmutableRelease(releaseId)
|
||||
if (immutableRelease) {
|
||||
this.setOutputs(immutableRelease.data, assetUrls)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
this.setOutputs(releaseData, assetUrls)
|
||||
}
|
||||
|
||||
private async publishImmutableRelease(releaseId: number): Promise<CreateOrUpdateReleaseResponse | undefined> {
|
||||
// Check if immutableCreate is on and createdDraft is off
|
||||
if (!this.inputs.immutableCreate || this.inputs.createdDraft) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return await this.releases.update(
|
||||
releaseId,
|
||||
this.inputs.tag,
|
||||
undefined, // body is omitted
|
||||
undefined, // commit is omitted
|
||||
this.inputs.discussionCategory,
|
||||
false, // We want to publish the release, set draft to false
|
||||
this.inputs.makeLatest,
|
||||
this.inputs.createdReleaseName,
|
||||
this.inputs.createdPrerelease
|
||||
)
|
||||
}
|
||||
|
||||
private setOutputs(releaseData: any, assetUrls: Record<string, string>): void {
|
||||
this.outputs.applyReleaseData(releaseData)
|
||||
this.outputs.applyAssetUrls(assetUrls)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface Inputs {
|
||||
readonly createdReleaseName?: string
|
||||
readonly discussionCategory?: string
|
||||
readonly generateReleaseNotes: boolean
|
||||
readonly immutableCreate: boolean
|
||||
readonly makeLatest?: "legacy" | "true" | "false" | undefined
|
||||
readonly omitBodyDuringUpdate: boolean
|
||||
readonly owner: string
|
||||
@@ -137,6 +138,11 @@ export class CoreInputs implements Inputs {
|
||||
return generate == "true"
|
||||
}
|
||||
|
||||
get immutableCreate(): boolean {
|
||||
const immutable = core.getInput("immutableCreate")
|
||||
return immutable != "false"
|
||||
}
|
||||
|
||||
get makeLatest(): "legacy" | "true" | "false" | undefined {
|
||||
let latest = core.getInput("makeLatest")
|
||||
if (latest == "true" || latest == "false" || latest == "legacy") {
|
||||
|
||||
7
tsconfig.test.json
Normal file
7
tsconfig.test.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": ["src/**/*", "__tests__/**/*"]
|
||||
}
|
||||
Reference in New Issue
Block a user