Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f36794624f | ||
|
|
b0c22f0188 |
@@ -13,7 +13,6 @@ This action will create a github release and optionally upload an artifact to it
|
|||||||
- **draft**: Optionally marks this release as a draft release. Set to `true` to enable.
|
- **draft**: Optionally marks this release as a draft release. Set to `true` to enable.
|
||||||
- **name**: An optional name for the release. If this is omitted the tag will be used.
|
- **name**: An optional name for the release. If this is omitted the tag will be used.
|
||||||
- **prerelease**: Optionally marks this release as prerelease. Set to true to enable.
|
- **prerelease**: Optionally marks this release as prerelease. Set to true to enable.
|
||||||
- **replacesArtifacts**: Indicates if existing release artifacts should be replaced. Defaults to true.
|
|
||||||
- **tag**: An optional tag for the release. If this is omitted the git ref will be used (if it is a tag).
|
- **tag**: An optional tag for the release. If this is omitted the git ref will be used (if it is a tag).
|
||||||
- **token**: (**Required**) The Github token. Typically this will be `${{ secrets.GITHUB_TOKEN }}`.
|
- **token**: (**Required**) The Github token. Typically this will be `${{ secrets.GITHUB_TOKEN }}`.
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import { Releases } from "../src/Releases";
|
|||||||
import { ArtifactUploader } from "../src/ArtifactUploader";
|
import { ArtifactUploader } from "../src/ArtifactUploader";
|
||||||
|
|
||||||
const createMock = jest.fn()
|
const createMock = jest.fn()
|
||||||
const deleteMock = jest.fn()
|
|
||||||
const getMock = jest.fn()
|
const getMock = jest.fn()
|
||||||
const listArtifactsMock = jest.fn()
|
|
||||||
const listMock = jest.fn()
|
const listMock = jest.fn()
|
||||||
const updateMock = jest.fn()
|
const updateMock = jest.fn()
|
||||||
const uploadMock = jest.fn()
|
const uploadMock = jest.fn()
|
||||||
@@ -23,8 +21,6 @@ const draft = true
|
|||||||
const id = 100
|
const id = 100
|
||||||
const name = 'name'
|
const name = 'name'
|
||||||
const prerelease = true
|
const prerelease = true
|
||||||
const releaseId = 101
|
|
||||||
const replacesArtifacts = true
|
|
||||||
const tag = 'tag'
|
const tag = 'tag'
|
||||||
const token = 'token'
|
const token = 'token'
|
||||||
const url = 'http://api.example.com'
|
const url = 'http://api.example.com'
|
||||||
@@ -55,7 +51,7 @@ describe("Action", () => {
|
|||||||
await action.perform()
|
await action.perform()
|
||||||
|
|
||||||
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
||||||
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
|
expect(uploadMock).toBeCalledWith(artifacts, url)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('creates release if no draft releases', async () => {
|
it('creates release if no draft releases', async () => {
|
||||||
@@ -71,7 +67,7 @@ describe("Action", () => {
|
|||||||
await action.perform()
|
await action.perform()
|
||||||
|
|
||||||
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
||||||
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
|
expect(uploadMock).toBeCalledWith(artifacts, url)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -81,7 +77,7 @@ describe("Action", () => {
|
|||||||
await action.perform()
|
await action.perform()
|
||||||
|
|
||||||
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
||||||
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
|
expect(uploadMock).toBeCalledWith(artifacts, url)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws error when create fails', async () => {
|
it('throws error when create fails', async () => {
|
||||||
@@ -152,7 +148,7 @@ describe("Action", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
|
||||||
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
|
expect(uploadMock).toBeCalledWith(artifacts, url)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('updates draft release', async () => {
|
it('updates draft release', async () => {
|
||||||
@@ -169,7 +165,7 @@ describe("Action", () => {
|
|||||||
await action.perform()
|
await action.perform()
|
||||||
|
|
||||||
expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease)
|
expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease)
|
||||||
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
|
expect(uploadMock).toBeCalledWith(artifacts, url)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -189,7 +185,7 @@ describe("Action", () => {
|
|||||||
await action.perform()
|
await action.perform()
|
||||||
|
|
||||||
expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease)
|
expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease)
|
||||||
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
|
expect(uploadMock).toBeCalledWith(artifacts, url)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -203,18 +199,15 @@ describe("Action", () => {
|
|||||||
const MockReleases = jest.fn<Releases, any>(() => {
|
const MockReleases = jest.fn<Releases, any>(() => {
|
||||||
return {
|
return {
|
||||||
create: createMock,
|
create: createMock,
|
||||||
deleteArtifact: deleteMock,
|
|
||||||
getByTag: getMock,
|
getByTag: getMock,
|
||||||
listArtifactsForRelease: listArtifactsMock,
|
|
||||||
listReleases: listMock,
|
listReleases: listMock,
|
||||||
update: updateMock,
|
update: updateMock,
|
||||||
uploadArtifact: jest.fn()
|
uploadArtifact: uploadMock
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
createMock.mockResolvedValue({
|
createMock.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
id: releaseId,
|
|
||||||
upload_url: url
|
upload_url: url
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -228,7 +221,6 @@ describe("Action", () => {
|
|||||||
})
|
})
|
||||||
updateMock.mockResolvedValue({
|
updateMock.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
id: releaseId,
|
|
||||||
upload_url: url
|
upload_url: url
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -243,7 +235,6 @@ describe("Action", () => {
|
|||||||
draft: draft,
|
draft: draft,
|
||||||
name: name,
|
name: name,
|
||||||
prerelease: prerelease,
|
prerelease: prerelease,
|
||||||
replacesArtifacts: replacesArtifacts,
|
|
||||||
tag: tag,
|
tag: tag,
|
||||||
token: token,
|
token: token,
|
||||||
readArtifact: () => artifactData
|
readArtifact: () => artifactData
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Artifact } from "../src/Artifact"
|
import { Artifact } from "../src/Artifact"
|
||||||
import { GithubArtifactUploader } from "../src/ArtifactUploader"
|
import { GithubArtifactUploader } from "../src/ArtifactUploader"
|
||||||
import { Releases } from "../src/Releases";
|
import { Releases } from "../src/Releases";
|
||||||
import { RequestError } from '@octokit/request-error'
|
|
||||||
|
|
||||||
const artifacts = [
|
const artifacts = [
|
||||||
new Artifact('a/art1'),
|
new Artifact('a/art1'),
|
||||||
@@ -9,12 +8,8 @@ const artifacts = [
|
|||||||
]
|
]
|
||||||
const fileContents = Buffer.from('artful facts', 'utf-8')
|
const fileContents = Buffer.from('artful facts', 'utf-8')
|
||||||
const contentLength = 42
|
const contentLength = 42
|
||||||
const releaseId = 100
|
|
||||||
const url = 'http://api.example.com'
|
|
||||||
|
|
||||||
const deleteMock = jest.fn()
|
|
||||||
const listArtifactsMock = jest.fn()
|
|
||||||
const uploadMock = jest.fn()
|
const uploadMock = jest.fn()
|
||||||
|
const url = 'http://api.example.com'
|
||||||
|
|
||||||
jest.mock('fs', () => {
|
jest.mock('fs', () => {
|
||||||
return {
|
return {
|
||||||
@@ -24,184 +19,27 @@ jest.mock('fs', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('ArtifactUploader', () => {
|
describe('ArtifactUploader', () => {
|
||||||
beforeEach(() => {
|
it('uploads artifacts', () => {
|
||||||
deleteMock.mockClear()
|
const uploader = createUploader()
|
||||||
listArtifactsMock.mockClear()
|
|
||||||
uploadMock.mockClear()
|
uploader.uploadArtifacts(artifacts, url)
|
||||||
})
|
|
||||||
|
|
||||||
it('replaces all artifacts', async () => {
|
|
||||||
mockDeleteSuccess()
|
|
||||||
mockListWithAssets()
|
|
||||||
mockUploadArtifact()
|
|
||||||
const uploader = createUploader(true)
|
|
||||||
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
|
|
||||||
expect(uploadMock).toBeCalledTimes(2)
|
expect(uploadMock).toBeCalledTimes(2)
|
||||||
expect(uploadMock)
|
expect(uploadMock)
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
||||||
expect(uploadMock)
|
expect(uploadMock)
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledTimes(2)
|
|
||||||
expect(deleteMock).toBeCalledWith(1)
|
|
||||||
expect(deleteMock).toBeCalledWith(2)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('replaces no artifacts when previous asset list empty', async () => {
|
function createUploader(): GithubArtifactUploader {
|
||||||
mockDeleteSuccess()
|
|
||||||
mockListWithoutAssets()
|
|
||||||
mockUploadArtifact()
|
|
||||||
const uploader = createUploader(true)
|
|
||||||
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
|
|
||||||
expect(uploadMock).toBeCalledTimes(2)
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledTimes(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('retry when upload failed with 5xx response', async () => {
|
|
||||||
mockListWithoutAssets()
|
|
||||||
mockUploadArtifact(500, 2)
|
|
||||||
const uploader = createUploader(true)
|
|
||||||
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
|
|
||||||
expect(uploadMock).toBeCalledTimes(4)
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledTimes(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('abort when upload failed with 5xx response after 3 attemps', async () => {
|
|
||||||
mockListWithoutAssets()
|
|
||||||
mockUploadArtifact(500, 4)
|
|
||||||
const uploader = createUploader(true)
|
|
||||||
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
|
|
||||||
expect(uploadMock).toBeCalledTimes(5)
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledTimes(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('abort when upload failed with non-5xx response', async () => {
|
|
||||||
mockListWithoutAssets()
|
|
||||||
mockUploadArtifact(401, 2)
|
|
||||||
const uploader = createUploader(true)
|
|
||||||
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
|
|
||||||
expect(uploadMock).toBeCalledTimes(2)
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledTimes(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('throws error from replace', async () => {
|
|
||||||
mockDeleteError()
|
|
||||||
mockListWithAssets()
|
|
||||||
mockUploadArtifact()
|
|
||||||
const uploader = createUploader(true)
|
|
||||||
|
|
||||||
expect.hasAssertions()
|
|
||||||
try {
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
} catch (error) {
|
|
||||||
expect(error).toEqual("error")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('updates all artifacts, delete none', async () => {
|
|
||||||
mockDeleteError()
|
|
||||||
mockListWithAssets()
|
|
||||||
mockUploadArtifact()
|
|
||||||
const uploader = createUploader(false)
|
|
||||||
|
|
||||||
await uploader.uploadArtifacts(artifacts, releaseId, url)
|
|
||||||
|
|
||||||
expect(uploadMock).toBeCalledTimes(2)
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art1')
|
|
||||||
expect(uploadMock)
|
|
||||||
.toBeCalledWith(url, contentLength, 'raw', fileContents, 'art2')
|
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledTimes(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
function createUploader(replaces: boolean): GithubArtifactUploader {
|
|
||||||
const MockReleases = jest.fn<Releases, any>(() => {
|
const MockReleases = jest.fn<Releases, any>(() => {
|
||||||
return {
|
return {
|
||||||
create: jest.fn(),
|
|
||||||
deleteArtifact: deleteMock,
|
|
||||||
getByTag: jest.fn(),
|
getByTag: jest.fn(),
|
||||||
listArtifactsForRelease: listArtifactsMock,
|
create: jest.fn(),
|
||||||
listReleases: jest.fn(),
|
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
uploadArtifact: uploadMock
|
uploadArtifact: uploadMock
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return new GithubArtifactUploader(new MockReleases(), replaces)
|
return new GithubArtifactUploader(new MockReleases())
|
||||||
}
|
|
||||||
|
|
||||||
function mockDeleteError(): any {
|
|
||||||
deleteMock.mockRejectedValue("error")
|
|
||||||
}
|
|
||||||
|
|
||||||
function mockDeleteSuccess(): any {
|
|
||||||
deleteMock.mockResolvedValue({})
|
|
||||||
}
|
|
||||||
|
|
||||||
function mockListWithAssets() {
|
|
||||||
listArtifactsMock.mockResolvedValue({
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
name: "art1",
|
|
||||||
id: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "art2",
|
|
||||||
id: 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function mockListWithoutAssets() {
|
|
||||||
listArtifactsMock.mockResolvedValue({ data: [] })
|
|
||||||
}
|
|
||||||
|
|
||||||
function mockUploadArtifact(status: number = 200, failures: number = 0) {
|
|
||||||
const error = new RequestError(`HTTP ${status}`, status, { headers: {}, request: { method: 'GET', url: '', headers: {} } })
|
|
||||||
for (let index = 0; index < failures; index++) {
|
|
||||||
uploadMock.mockRejectedValueOnce(error)
|
|
||||||
}
|
|
||||||
uploadMock.mockResolvedValue({})
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -144,17 +144,6 @@ describe('Inputs', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('replacesArtifacts', () => {
|
|
||||||
it('returns false', () => {
|
|
||||||
expect(inputs.replacesArtifacts).toBe(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns true', () => {
|
|
||||||
mockGetInput.mockReturnValue('true')
|
|
||||||
expect(inputs.replacesArtifacts).toBe(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('tag', () => {
|
describe('tag', () => {
|
||||||
it('returns input tag', () => {
|
it('returns input tag', () => {
|
||||||
mockGetInput.mockReturnValue('tag')
|
mockGetInput.mockReturnValue('tag')
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ inputs:
|
|||||||
description: 'An optional flag which indicates if we should update a release if it already exists. Defaults to false.'
|
description: 'An optional flag which indicates if we should update a release if it already exists. Defaults to false.'
|
||||||
default: ''
|
default: ''
|
||||||
artifact:
|
artifact:
|
||||||
deprecationMessage: Use 'artifacts' instead.
|
|
||||||
description: 'An optional set of paths representing artifacts to upload to the release. This may be a single path or a comma delimited list of paths (or globs)'
|
description: 'An optional set of paths representing artifacts to upload to the release. This may be a single path or a comma delimited list of paths (or globs)'
|
||||||
default: ''
|
default: ''
|
||||||
artifacts:
|
artifacts:
|
||||||
@@ -32,10 +31,7 @@ inputs:
|
|||||||
default: ''
|
default: ''
|
||||||
prerelease:
|
prerelease:
|
||||||
description: "Optionally marks this release as prerelease. Set to true to enable."
|
description: "Optionally marks this release as prerelease. Set to true to enable."
|
||||||
default: ''
|
default: ''
|
||||||
replacesArtifacts:
|
|
||||||
description: "Indicates if existing release artifacts should be replaced. Defaults to true."
|
|
||||||
default: 'true'
|
|
||||||
tag:
|
tag:
|
||||||
description: 'An optional tag for the release. If this is omitted the git ref will be used (if it is a tag).'
|
description: 'An optional tag for the release. If this is omitted the git ref will be used (if it is a tag).'
|
||||||
default: ''
|
default: ''
|
||||||
|
|||||||
105
lib/Action.js
105
lib/Action.js
@@ -1,4 +1,13 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const ErrorMessage_1 = require("./ErrorMessage");
|
const ErrorMessage_1 = require("./ErrorMessage");
|
||||||
class Action {
|
class Action {
|
||||||
@@ -7,62 +16,72 @@ class Action {
|
|||||||
this.releases = releases;
|
this.releases = releases;
|
||||||
this.uploader = uploader;
|
this.uploader = uploader;
|
||||||
}
|
}
|
||||||
async perform() {
|
perform() {
|
||||||
const releaseResponse = await this.createOrUpdateRelease();
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const releaseId = releaseResponse.id;
|
const uploadUrl = yield this.createOrUpdateRelease();
|
||||||
const uploadUrl = releaseResponse.upload_url;
|
const artifacts = this.inputs.artifacts;
|
||||||
const artifacts = this.inputs.artifacts;
|
if (artifacts.length > 0) {
|
||||||
if (artifacts.length > 0) {
|
yield this.uploader.uploadArtifacts(artifacts, uploadUrl);
|
||||||
await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async createOrUpdateRelease() {
|
|
||||||
if (this.inputs.allowUpdates) {
|
|
||||||
try {
|
|
||||||
const getResponse = await this.releases.getByTag(this.inputs.tag);
|
|
||||||
return await this.updateRelease(getResponse.data.id);
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
});
|
||||||
if (this.noPublishedRelease(error)) {
|
}
|
||||||
return await this.updateDraftOrCreateRelease();
|
createOrUpdateRelease() {
|
||||||
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
|
if (this.inputs.allowUpdates) {
|
||||||
|
try {
|
||||||
|
const getResponse = yield this.releases.getByTag(this.inputs.tag);
|
||||||
|
return yield this.updateRelease(getResponse.data.id);
|
||||||
}
|
}
|
||||||
else {
|
catch (error) {
|
||||||
throw error;
|
if (this.noPublishedRelease(error)) {
|
||||||
|
return yield this.updateDraftOrCreateRelease();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else {
|
return yield this.createRelease();
|
||||||
return await this.createRelease();
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
async updateRelease(id) {
|
updateRelease(id) {
|
||||||
const response = await this.releases.update(id, this.inputs.tag, this.inputs.body, this.inputs.commit, this.inputs.draft, this.inputs.name, this.inputs.prerelease);
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return response.data;
|
const response = yield this.releases.update(id, this.inputs.tag, this.inputs.body, this.inputs.commit, this.inputs.draft, this.inputs.name, this.inputs.prerelease);
|
||||||
|
return response.data.upload_url;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
noPublishedRelease(error) {
|
noPublishedRelease(error) {
|
||||||
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
|
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
|
||||||
return errorMessage.status == 404;
|
return errorMessage.status == 404;
|
||||||
}
|
}
|
||||||
async updateDraftOrCreateRelease() {
|
updateDraftOrCreateRelease() {
|
||||||
const draftReleaseId = await this.findMatchingDraftReleaseId();
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (draftReleaseId) {
|
const draftReleaseId = yield this.findMatchingDraftReleaseId();
|
||||||
return await this.updateRelease(draftReleaseId);
|
if (draftReleaseId) {
|
||||||
}
|
return yield this.updateRelease(draftReleaseId);
|
||||||
else {
|
}
|
||||||
return await this.createRelease();
|
else {
|
||||||
}
|
return yield this.createRelease();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
async findMatchingDraftReleaseId() {
|
findMatchingDraftReleaseId() {
|
||||||
var _a;
|
var _a;
|
||||||
const tag = this.inputs.tag;
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const response = await this.releases.listReleases();
|
const tag = this.inputs.tag;
|
||||||
const releases = response.data;
|
const response = yield this.releases.listReleases();
|
||||||
const draftRelease = releases.find(release => release.draft && release.tag_name == tag);
|
const releases = response.data;
|
||||||
return (_a = draftRelease) === null || _a === void 0 ? void 0 : _a.id;
|
const draftRelease = releases.find(release => release.draft && release.tag_name == tag);
|
||||||
|
return (_a = draftRelease) === null || _a === void 0 ? void 0 : _a.id;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
async createRelease() {
|
createRelease() {
|
||||||
const response = await this.releases.create(this.inputs.tag, this.inputs.body, this.inputs.commit, this.inputs.draft, this.inputs.name, this.inputs.prerelease);
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
return response.data;
|
const response = yield this.releases.create(this.inputs.tag, this.inputs.body, this.inputs.commit, this.inputs.draft, this.inputs.name, this.inputs.prerelease);
|
||||||
|
return response.data.upload_url;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Action = Action;
|
exports.Action = Action;
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
if (mod && mod.__esModule) return mod;
|
if (mod && mod.__esModule) return mod;
|
||||||
var result = {};
|
var result = {};
|
||||||
@@ -9,47 +18,21 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const core = __importStar(require("@actions/core"));
|
const core = __importStar(require("@actions/core"));
|
||||||
class GithubArtifactUploader {
|
class GithubArtifactUploader {
|
||||||
constructor(releases, replacesExistingArtifacts = true) {
|
constructor(releases) {
|
||||||
this.releases = releases;
|
this.releases = releases;
|
||||||
this.replacesExistingArtifacts = replacesExistingArtifacts;
|
|
||||||
}
|
}
|
||||||
async uploadArtifacts(artifacts, releaseId, uploadUrl) {
|
uploadArtifacts(artifacts, uploadUrl) {
|
||||||
if (this.replacesExistingArtifacts) {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
await this.deleteUpdatedArtifacts(artifacts, releaseId);
|
artifacts.forEach((artifact) => __awaiter(this, void 0, void 0, function* () {
|
||||||
}
|
try {
|
||||||
for (const artifact of artifacts) {
|
yield this.releases.uploadArtifact(uploadUrl, artifact.contentLength, artifact.contentType, artifact.readFile(), artifact.name);
|
||||||
await this.uploadArtifact(artifact, uploadUrl);
|
}
|
||||||
}
|
catch (error) {
|
||||||
}
|
const message = `Failed to upload artifact ${artifact.name}. Does it already exist?`;
|
||||||
async uploadArtifact(artifact, uploadUrl, retry = 3) {
|
core.warning(message);
|
||||||
try {
|
}
|
||||||
core.debug(`Uploading artifact ${artifact.name}...`);
|
}));
|
||||||
await this.releases.uploadArtifact(uploadUrl, artifact.contentLength, artifact.contentType, artifact.readFile(), artifact.name);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if (error.status >= 500 && retry > 0) {
|
|
||||||
core.warning(`Failed to upload artifact ${artifact.name}. ${error.message}. Retrying...`);
|
|
||||||
await this.uploadArtifact(artifact, uploadUrl, retry - 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
core.warning(`Failed to upload artifact ${artifact.name}. ${error.message}.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async deleteUpdatedArtifacts(artifacts, releaseId) {
|
|
||||||
const response = await this.releases.listArtifactsForRelease(releaseId);
|
|
||||||
const releaseAssets = response.data;
|
|
||||||
const assetByName = {};
|
|
||||||
releaseAssets.forEach(asset => {
|
|
||||||
assetByName[asset.name] = asset;
|
|
||||||
});
|
});
|
||||||
for (const artifact of artifacts) {
|
|
||||||
const asset = assetByName[artifact.name];
|
|
||||||
if (asset) {
|
|
||||||
core.debug(`Deleting existing artifact ${artifact.name}...`);
|
|
||||||
await this.releases.deleteArtifact(asset.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.GithubArtifactUploader = GithubArtifactUploader;
|
exports.GithubArtifactUploader = GithubArtifactUploader;
|
||||||
|
|||||||
@@ -59,12 +59,8 @@ class CoreInputs {
|
|||||||
return this.tag;
|
return this.tag;
|
||||||
}
|
}
|
||||||
get prerelease() {
|
get prerelease() {
|
||||||
const preRelease = core.getInput('prerelease');
|
const draft = core.getInput('prerelease');
|
||||||
return preRelease == 'true';
|
return draft == 'true';
|
||||||
}
|
|
||||||
get replacesArtifacts() {
|
|
||||||
const replaces = core.getInput('replacesArtifacts');
|
|
||||||
return replaces == 'true';
|
|
||||||
}
|
}
|
||||||
get tag() {
|
get tag() {
|
||||||
const tag = core.getInput('tag');
|
const tag = core.getInput('tag');
|
||||||
|
|||||||
31
lib/Main.js
31
lib/Main.js
@@ -1,4 +1,13 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
var __importStar = (this && this.__importStar) || function (mod) {
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
if (mod && mod.__esModule) return mod;
|
if (mod && mod.__esModule) return mod;
|
||||||
var result = {};
|
var result = {};
|
||||||
@@ -15,15 +24,17 @@ const Action_1 = require("./Action");
|
|||||||
const ArtifactUploader_1 = require("./ArtifactUploader");
|
const ArtifactUploader_1 = require("./ArtifactUploader");
|
||||||
const ArtifactGlobber_1 = require("./ArtifactGlobber");
|
const ArtifactGlobber_1 = require("./ArtifactGlobber");
|
||||||
const ErrorMessage_1 = require("./ErrorMessage");
|
const ErrorMessage_1 = require("./ErrorMessage");
|
||||||
async function run() {
|
function run() {
|
||||||
try {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
const action = createAction();
|
try {
|
||||||
await action.perform();
|
const action = createAction();
|
||||||
}
|
yield action.perform();
|
||||||
catch (error) {
|
}
|
||||||
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
|
catch (error) {
|
||||||
core.setFailed(errorMessage.toString());
|
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
|
||||||
}
|
core.setFailed(errorMessage.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function createAction() {
|
function createAction() {
|
||||||
const token = core.getInput('token');
|
const token = core.getInput('token');
|
||||||
@@ -32,7 +43,7 @@ function createAction() {
|
|||||||
const globber = new ArtifactGlobber_1.FileArtifactGlobber();
|
const globber = new ArtifactGlobber_1.FileArtifactGlobber();
|
||||||
const inputs = new Inputs_1.CoreInputs(globber, context);
|
const inputs = new Inputs_1.CoreInputs(globber, context);
|
||||||
const releases = new Releases_1.GithubReleases(context, git);
|
const releases = new Releases_1.GithubReleases(context, git);
|
||||||
const uploader = new ArtifactUploader_1.GithubArtifactUploader(releases, inputs.replacesArtifacts);
|
const uploader = new ArtifactUploader_1.GithubArtifactUploader(releases);
|
||||||
return new Action_1.Action(inputs, releases, uploader);
|
return new Action_1.Action(inputs, releases, uploader);
|
||||||
}
|
}
|
||||||
run();
|
run();
|
||||||
|
|||||||
111
lib/Releases.js
111
lib/Releases.js
@@ -1,71 +1,76 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||||
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||||
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||||
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||||
|
});
|
||||||
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
class GithubReleases {
|
class GithubReleases {
|
||||||
constructor(context, git) {
|
constructor(context, git) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.git = git;
|
this.git = git;
|
||||||
}
|
}
|
||||||
async create(tag, body, commitHash, draft, name, prerelease) {
|
create(tag, body, commitHash, draft, name, prerelease) {
|
||||||
return this.git.repos.createRelease({
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
body: body,
|
return this.git.repos.createRelease({
|
||||||
name: name,
|
body: body,
|
||||||
draft: draft,
|
name: name,
|
||||||
owner: this.context.repo.owner,
|
draft: draft,
|
||||||
prerelease: prerelease,
|
owner: this.context.repo.owner,
|
||||||
repo: this.context.repo.repo,
|
prerelease: prerelease,
|
||||||
target_commitish: commitHash,
|
repo: this.context.repo.repo,
|
||||||
tag_name: tag
|
target_commitish: commitHash,
|
||||||
|
tag_name: tag
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async deleteArtifact(assetId) {
|
listReleases() {
|
||||||
return this.git.repos.deleteReleaseAsset({
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
asset_id: assetId,
|
return this.git.repos.listReleases({
|
||||||
owner: this.context.repo.owner,
|
owner: this.context.repo.owner,
|
||||||
repo: this.context.repo.repo
|
repo: this.context.repo.repo
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async listArtifactsForRelease(releaseId) {
|
getByTag(tag) {
|
||||||
return this.git.repos.listAssetsForRelease({
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
owner: this.context.repo.owner,
|
return this.git.repos.getReleaseByTag({
|
||||||
release_id: releaseId,
|
owner: this.context.repo.owner,
|
||||||
repo: this.context.repo.repo
|
repo: this.context.repo.repo,
|
||||||
|
tag: tag
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async listReleases() {
|
update(id, tag, body, commitHash, draft, name, prerelease) {
|
||||||
return this.git.repos.listReleases({
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
owner: this.context.repo.owner,
|
return this.git.repos.updateRelease({
|
||||||
repo: this.context.repo.repo
|
release_id: id,
|
||||||
|
body: body,
|
||||||
|
name: name,
|
||||||
|
draft: draft,
|
||||||
|
owner: this.context.repo.owner,
|
||||||
|
prerelease: prerelease,
|
||||||
|
repo: this.context.repo.repo,
|
||||||
|
target_commitish: commitHash,
|
||||||
|
tag_name: tag
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async getByTag(tag) {
|
uploadArtifact(assetUrl, contentLength, contentType, file, name) {
|
||||||
return this.git.repos.getReleaseByTag({
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
owner: this.context.repo.owner,
|
return this.git.repos.uploadReleaseAsset({
|
||||||
repo: this.context.repo.repo,
|
url: assetUrl,
|
||||||
tag: tag
|
headers: {
|
||||||
});
|
"content-length": contentLength,
|
||||||
}
|
"content-type": contentType
|
||||||
async update(id, tag, body, commitHash, draft, name, prerelease) {
|
},
|
||||||
return this.git.repos.updateRelease({
|
file: file,
|
||||||
release_id: id,
|
name: name
|
||||||
body: body,
|
});
|
||||||
name: name,
|
|
||||||
draft: draft,
|
|
||||||
owner: this.context.repo.owner,
|
|
||||||
prerelease: prerelease,
|
|
||||||
repo: this.context.repo.repo,
|
|
||||||
target_commitish: commitHash,
|
|
||||||
tag_name: tag
|
|
||||||
});
|
|
||||||
}
|
|
||||||
async uploadArtifact(assetUrl, contentLength, contentType, file, name) {
|
|
||||||
return this.git.repos.uploadReleaseAsset({
|
|
||||||
url: assetUrl,
|
|
||||||
headers: {
|
|
||||||
"content-length": contentLength,
|
|
||||||
"content-type": contentType
|
|
||||||
},
|
|
||||||
file: file,
|
|
||||||
name: name
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
node_modules/.yarn-integrity
generated
vendored
35
node_modules/.yarn-integrity
generated
vendored
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"systemParams": "darwin-x64-79",
|
"systemParams": "darwin-x64-72",
|
||||||
"modulesFolders": [
|
"modulesFolders": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
],
|
],
|
||||||
@@ -646,36 +646,11 @@
|
|||||||
"files": [],
|
"files": [],
|
||||||
"artifacts": {
|
"artifacts": {
|
||||||
"fsevents@1.2.9": [
|
"fsevents@1.2.9": [
|
||||||
"build",
|
"lib",
|
||||||
"build/.target.mk",
|
"lib/binding",
|
||||||
"build/Makefile",
|
|
||||||
"build/Release",
|
|
||||||
"build/Release/.deps",
|
|
||||||
"build/Release/.deps/Release",
|
|
||||||
"build/Release/.deps/Release/.node.d",
|
|
||||||
"build/Release/.deps/Release/fse.node.d",
|
|
||||||
"build/Release/.deps/Release/obj.target",
|
|
||||||
"build/Release/.deps/Release/obj.target/action_after_build.stamp.d",
|
|
||||||
"build/Release/.deps/Release/obj.target/fse",
|
|
||||||
"build/Release/.deps/Release/obj.target/fse/fsevents.o.d",
|
|
||||||
"build/Release/.deps/Users",
|
|
||||||
"build/Release/.deps/Users/nickcipollo",
|
|
||||||
"build/Release/.deps/Users/nickcipollo/src",
|
|
||||||
"build/Release/.deps/Users/nickcipollo/src/release-action",
|
|
||||||
"build/Release/.node",
|
|
||||||
"build/Release/fse.node",
|
|
||||||
"build/Release/obj.target",
|
|
||||||
"build/Release/obj.target/action_after_build.stamp",
|
|
||||||
"build/Release/obj.target/fse",
|
|
||||||
"build/Release/obj.target/fse/fsevents.o",
|
|
||||||
"build/action_after_build.target.mk",
|
|
||||||
"build/binding.Makefile",
|
|
||||||
"build/config.gypi",
|
|
||||||
"build/fse.target.mk",
|
|
||||||
"build/gyp-mac-tool",
|
|
||||||
"lib/binding/Release",
|
"lib/binding/Release",
|
||||||
"lib/binding/Release/node-v79-darwin-x64",
|
"lib/binding/Release/node-v72-darwin-x64",
|
||||||
"lib/binding/Release/node-v79-darwin-x64/fse.node"
|
"lib/binding/Release/node-v72-darwin-x64/fse.node"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Inputs } from "./Inputs";
|
import { Inputs } from "./Inputs";
|
||||||
import { Releases } from "./Releases";
|
import { Releases } from "./Releases";
|
||||||
import { ReposCreateReleaseResponse } from "@octokit/rest";
|
|
||||||
import { ArtifactUploader } from "./ArtifactUploader";
|
import { ArtifactUploader } from "./ArtifactUploader";
|
||||||
import { ErrorMessage } from "./ErrorMessage";
|
import { ErrorMessage } from "./ErrorMessage";
|
||||||
|
|
||||||
@@ -16,17 +15,15 @@ export class Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async perform() {
|
async perform() {
|
||||||
const releaseResponse = await this.createOrUpdateRelease();
|
const uploadUrl = await this.createOrUpdateRelease()
|
||||||
const releaseId = releaseResponse.id
|
|
||||||
const uploadUrl = releaseResponse.upload_url
|
|
||||||
|
|
||||||
const artifacts = this.inputs.artifacts
|
const artifacts = this.inputs.artifacts
|
||||||
if (artifacts.length > 0) {
|
if (artifacts.length > 0) {
|
||||||
await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl)
|
await this.uploader.uploadArtifacts(artifacts, uploadUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createOrUpdateRelease(): Promise<ReposCreateReleaseResponse> {
|
private async createOrUpdateRelease(): Promise<string> {
|
||||||
if (this.inputs.allowUpdates) {
|
if (this.inputs.allowUpdates) {
|
||||||
try {
|
try {
|
||||||
const getResponse = await this.releases.getByTag(this.inputs.tag)
|
const getResponse = await this.releases.getByTag(this.inputs.tag)
|
||||||
@@ -43,7 +40,7 @@ export class Action {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateRelease(id: number): Promise<ReposCreateReleaseResponse> {
|
private async updateRelease(id: number): Promise<string> {
|
||||||
const response = await this.releases.update(
|
const response = await this.releases.update(
|
||||||
id,
|
id,
|
||||||
this.inputs.tag,
|
this.inputs.tag,
|
||||||
@@ -54,7 +51,7 @@ export class Action {
|
|||||||
this.inputs.prerelease
|
this.inputs.prerelease
|
||||||
)
|
)
|
||||||
|
|
||||||
return response.data
|
return response.data.upload_url
|
||||||
}
|
}
|
||||||
|
|
||||||
private noPublishedRelease(error: any): boolean {
|
private noPublishedRelease(error: any): boolean {
|
||||||
@@ -62,7 +59,7 @@ export class Action {
|
|||||||
return errorMessage.status == 404
|
return errorMessage.status == 404
|
||||||
}
|
}
|
||||||
|
|
||||||
private async updateDraftOrCreateRelease(): Promise<ReposCreateReleaseResponse> {
|
private async updateDraftOrCreateRelease(): Promise<string> {
|
||||||
const draftReleaseId = await this.findMatchingDraftReleaseId()
|
const draftReleaseId = await this.findMatchingDraftReleaseId()
|
||||||
if (draftReleaseId) {
|
if (draftReleaseId) {
|
||||||
return await this.updateRelease(draftReleaseId)
|
return await this.updateRelease(draftReleaseId)
|
||||||
@@ -80,7 +77,7 @@ export class Action {
|
|||||||
return draftRelease?.id
|
return draftRelease?.id
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createRelease(): Promise<ReposCreateReleaseResponse> {
|
private async createRelease(): Promise<string> {
|
||||||
const response = await this.releases.create(
|
const response = await this.releases.create(
|
||||||
this.inputs.tag,
|
this.inputs.tag,
|
||||||
this.inputs.body,
|
this.inputs.body,
|
||||||
@@ -90,6 +87,6 @@ export class Action {
|
|||||||
this.inputs.prerelease
|
this.inputs.prerelease
|
||||||
)
|
)
|
||||||
|
|
||||||
return response.data
|
return response.data.upload_url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,61 +1,30 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import { Artifact } from "./Artifact";
|
import { Artifact } from "./Artifact";
|
||||||
import { Releases } from "./Releases";
|
import { Releases } from "./Releases";
|
||||||
import { ReposListAssetsForReleaseResponseItem } from "@octokit/rest";
|
|
||||||
|
|
||||||
export interface ArtifactUploader {
|
export interface ArtifactUploader {
|
||||||
uploadArtifacts(artifacts: Artifact[], releaseId: number, uploadUrl: string): Promise<void>
|
uploadArtifacts(artifacts: Artifact[], uploadUrl: string): Promise<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GithubArtifactUploader implements ArtifactUploader {
|
export class GithubArtifactUploader implements ArtifactUploader {
|
||||||
constructor(
|
private releases: Releases
|
||||||
private releases: Releases,
|
|
||||||
private replacesExistingArtifacts: boolean = true,
|
constructor(releases: Releases) {
|
||||||
) {
|
this.releases = releases
|
||||||
}
|
}
|
||||||
|
|
||||||
async uploadArtifacts(artifacts: Artifact[],
|
async uploadArtifacts(artifacts: Artifact[], uploadUrl: string) {
|
||||||
releaseId: number,
|
artifacts.forEach(async artifact => {
|
||||||
uploadUrl: string): Promise<void> {
|
try {
|
||||||
if (this.replacesExistingArtifacts) {
|
await this.releases.uploadArtifact(uploadUrl,
|
||||||
await this.deleteUpdatedArtifacts(artifacts, releaseId)
|
artifact.contentLength,
|
||||||
}
|
artifact.contentType,
|
||||||
for (const artifact of artifacts) {
|
artifact.readFile(),
|
||||||
await this.uploadArtifact(artifact, uploadUrl)
|
artifact.name)
|
||||||
}
|
} catch(error) {
|
||||||
}
|
const message = `Failed to upload artifact ${artifact.name}. Does it already exist?`
|
||||||
|
core.warning(message)
|
||||||
private async uploadArtifact(artifact: Artifact, uploadUrl: string, retry = 3) {
|
|
||||||
try {
|
|
||||||
core.debug(`Uploading artifact ${artifact.name}...`)
|
|
||||||
await this.releases.uploadArtifact(uploadUrl,
|
|
||||||
artifact.contentLength,
|
|
||||||
artifact.contentType,
|
|
||||||
artifact.readFile(),
|
|
||||||
artifact.name)
|
|
||||||
} catch (error) {
|
|
||||||
if (error.status >= 500 && retry > 0) {
|
|
||||||
core.warning(`Failed to upload artifact ${artifact.name}. ${error.message}. Retrying...`)
|
|
||||||
await this.uploadArtifact(artifact, uploadUrl, retry - 1)
|
|
||||||
} else {
|
|
||||||
core.warning(`Failed to upload artifact ${artifact.name}. ${error.message}.`)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async deleteUpdatedArtifacts(artifacts: Artifact[], releaseId: number): Promise<void> {
|
|
||||||
const response = await this.releases.listArtifactsForRelease(releaseId)
|
|
||||||
const releaseAssets = response.data
|
|
||||||
const assetByName: Record<string, ReposListAssetsForReleaseResponseItem> = {}
|
|
||||||
releaseAssets.forEach(asset => {
|
|
||||||
assetByName[asset.name] = asset
|
|
||||||
});
|
});
|
||||||
for (const artifact of artifacts) {
|
|
||||||
const asset = assetByName[artifact.name]
|
|
||||||
if (asset) {
|
|
||||||
core.debug(`Deleting existing artifact ${artifact.name}...`)
|
|
||||||
await this.releases.deleteArtifact(asset.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ export interface Inputs {
|
|||||||
readonly draft: boolean
|
readonly draft: boolean
|
||||||
readonly name: string
|
readonly name: string
|
||||||
readonly prerelease: boolean
|
readonly prerelease: boolean
|
||||||
readonly replacesArtifacts: boolean
|
|
||||||
readonly tag: string
|
readonly tag: string
|
||||||
readonly token: string
|
readonly token: string
|
||||||
}
|
}
|
||||||
@@ -80,13 +79,8 @@ export class CoreInputs implements Inputs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get prerelease(): boolean {
|
get prerelease(): boolean {
|
||||||
const preRelease = core.getInput('prerelease')
|
const draft = core.getInput('prerelease')
|
||||||
return preRelease == 'true'
|
return draft == 'true'
|
||||||
}
|
|
||||||
|
|
||||||
get replacesArtifacts(): boolean {
|
|
||||||
const replaces = core.getInput('replacesArtifacts')
|
|
||||||
return replaces == 'true'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get tag(): string {
|
get tag(): string {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function createAction(): Action {
|
|||||||
|
|
||||||
const inputs = new CoreInputs(globber, context)
|
const inputs = new CoreInputs(globber, context)
|
||||||
const releases = new GithubReleases(context, git)
|
const releases = new GithubReleases(context, git)
|
||||||
const uploader = new GithubArtifactUploader(releases, inputs.replacesArtifacts)
|
const uploader = new GithubArtifactUploader(releases)
|
||||||
return new Action(inputs, releases, uploader)
|
return new Action(inputs, releases, uploader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Context } from "@actions/github/lib/context";
|
import { Context } from "@actions/github/lib/context";
|
||||||
import { GitHub } from "@actions/github";
|
import { GitHub } from "@actions/github";
|
||||||
import { AnyResponse, Response, ReposDeleteReleaseAssetResponse, ReposListAssetsForReleaseResponse, ReposCreateReleaseResponse, ReposGetReleaseByTagResponse, ReposListReleasesResponse } from "@octokit/rest";
|
import { AnyResponse, Response, ReposCreateReleaseResponse, ReposGetReleaseByTagResponse, ReposListReleasesResponse } from "@octokit/rest";
|
||||||
|
|
||||||
export interface Releases {
|
export interface Releases {
|
||||||
create(
|
create(
|
||||||
@@ -12,12 +12,8 @@ export interface Releases {
|
|||||||
prerelease?: boolean
|
prerelease?: boolean
|
||||||
): Promise<Response<ReposCreateReleaseResponse>>
|
): Promise<Response<ReposCreateReleaseResponse>>
|
||||||
|
|
||||||
deleteArtifact(assetId: number): Promise<Response<ReposDeleteReleaseAssetResponse>>
|
|
||||||
|
|
||||||
getByTag(tag: string): Promise<Response<ReposGetReleaseByTagResponse>>
|
getByTag(tag: string): Promise<Response<ReposGetReleaseByTagResponse>>
|
||||||
|
|
||||||
listArtifactsForRelease(releaseId: number): Promise<Response<ReposListAssetsForReleaseResponse>>
|
|
||||||
|
|
||||||
listReleases(): Promise<Response<ReposListReleasesResponse>>
|
listReleases(): Promise<Response<ReposListReleasesResponse>>
|
||||||
|
|
||||||
update(
|
update(
|
||||||
@@ -68,26 +64,6 @@ export class GithubReleases implements Releases {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteArtifact(
|
|
||||||
assetId: number
|
|
||||||
): Promise<Response<ReposDeleteReleaseAssetResponse>> {
|
|
||||||
return this.git.repos.deleteReleaseAsset({
|
|
||||||
asset_id: assetId,
|
|
||||||
owner: this.context.repo.owner,
|
|
||||||
repo: this.context.repo.repo
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async listArtifactsForRelease(
|
|
||||||
releaseId: number
|
|
||||||
): Promise<Response<ReposListAssetsForReleaseResponse>> {
|
|
||||||
return this.git.repos.listAssetsForRelease({
|
|
||||||
owner: this.context.repo.owner,
|
|
||||||
release_id: releaseId,
|
|
||||||
repo: this.context.repo.repo
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
async listReleases(): Promise<Response<ReposListReleasesResponse>> {
|
async listReleases(): Promise<Response<ReposListReleasesResponse>> {
|
||||||
return this.git.repos.listReleases({
|
return this.git.repos.listReleases({
|
||||||
owner: this.context.repo.owner,
|
owner: this.context.repo.owner,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Basic Options */
|
/* Basic Options */
|
||||||
// "incremental": true, /* Enable incremental compilation */
|
// "incremental": true, /* Enable incremental compilation */
|
||||||
"target": "es2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
// "checkJs": true, /* Report errors in .js files. */
|
||||||
|
|||||||
Reference in New Issue
Block a user