11 Commits

Author SHA1 Message Date
Nick Cipollo
6c34249ffc Prepare 1.6.1 release
Some checks failed
PR Checks / check_pr (push) Has been cancelled
2020-03-05 13:25:53 -05:00
Nick Cipollo
c4e12dcecf Build debug 2020-03-05 13:22:45 -05:00
Nick Cipollo
791611e03e Tiny logging tweek 2020-03-05 13:12:22 -05:00
Nick Cipollo
2ea88b1f32 Add retry for uploading artifact (#13) 2020-03-05 11:39:02 -05:00
Nick Cipollo
d57d57cad2 Fixes #12 Artifacts will now be replaced 2020-03-02 22:20:41 -05:00
Nick Cipollo
767a5edcf4 Fix tests 2020-01-02 23:46:48 -05:00
Nick Cipollo
cffd02c48e Add artifact upload error handling 2020-01-02 23:31:20 -05:00
Nick Cipollo
04d64ce68e Fixes #8 Add support for draft release updating 2020-01-02 22:56:16 -05:00
Nick Cipollo
c8e9e33d90 Update jest 2020-01-02 17:59:03 -05:00
Nick Cipollo
8f1cb7790e Merge pull request #9 from ncipollo/dependabot/npm_and_yarn/handlebars-4.5.3
Bump handlebars from 4.1.2 to 4.5.3
2020-01-02 17:56:05 -05:00
dependabot[bot]
40267624b8 Bump handlebars from 4.1.2 to 4.5.3
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.1.2 to 4.5.3.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/wycats/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.1.2...v4.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2019-12-29 20:48:31 +00:00
20 changed files with 614 additions and 235 deletions

2
.gitignore vendored
View File

@@ -1,2 +1,2 @@
#node_modules/ # node_modules/
__tests__/runner/* __tests__/runner/*

View File

@@ -13,6 +13,7 @@ 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 }}`.

View File

@@ -5,7 +5,10 @@ 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 updateMock = jest.fn() const updateMock = jest.fn()
const uploadMock = jest.fn() const uploadMock = jest.fn()
@@ -20,6 +23,8 @@ 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'
@@ -28,6 +33,7 @@ describe("Action", () => {
beforeEach(() => { beforeEach(() => {
createMock.mockClear() createMock.mockClear()
getMock.mockClear() getMock.mockClear()
listMock.mockClear()
updateMock.mockClear() updateMock.mockClear()
uploadMock.mockClear() uploadMock.mockClear()
}) })
@@ -43,15 +49,30 @@ describe("Action", () => {
it('creates release if no release exists to update', async () => { it('creates release if no release exists to update', async () => {
const action = createAction(true, true) const action = createAction(true, true)
const error = { const error = { status: 404 }
status: 404
}
getMock.mockRejectedValue(error) getMock.mockRejectedValue(error)
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, url) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
})
it('creates release if no draft releases', async () => {
const action = createAction(true, true)
const error = { status: 404 }
getMock.mockRejectedValue(error)
listMock.mockResolvedValue({
data: [
{ id: id, draft: false, tag_name: tag }
]
})
await action.perform()
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
}) })
it('creates release then uploads artifact', async () => { it('creates release then uploads artifact', async () => {
@@ -60,7 +81,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, url) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
}) })
it('throws error when create fails', async () => { it('throws error when create fails', async () => {
@@ -131,7 +152,25 @@ describe("Action", () => {
} }
expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease) expect(createMock).toBeCalledWith(tag, body, commit, draft, name, prerelease)
expect(uploadMock).toBeCalledWith(artifacts, url) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
})
it('updates draft release', async () => {
const action = createAction(true, true)
const error = { status: 404 }
getMock.mockRejectedValue(error)
listMock.mockResolvedValue({
data: [
{ id: 123, draft: false, tag_name: tag },
{ id: id, draft: true, tag_name: tag }
]
})
await action.perform()
expect(updateMock).toBeCalledWith(id, tag, body, commit, draft, name, prerelease)
expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
}) })
it('updates release but does not upload if no artifact', async () => { it('updates release but does not upload if no artifact', async () => {
@@ -150,7 +189,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, url) expect(uploadMock).toBeCalledWith(artifacts, releaseId, url)
}) })
@@ -164,14 +203,18 @@ 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,
update: updateMock, update: updateMock,
uploadArtifact: uploadMock uploadArtifact: jest.fn()
} }
}) })
createMock.mockResolvedValue({ createMock.mockResolvedValue({
data: { data: {
id: releaseId,
upload_url: url upload_url: url
} }
}) })
@@ -180,8 +223,12 @@ describe("Action", () => {
id: id id: id
} }
}) })
listMock.mockResolvedValue({
data: []
})
updateMock.mockResolvedValue({ updateMock.mockResolvedValue({
data: { data: {
id: releaseId,
upload_url: url upload_url: url
} }
}) })
@@ -196,6 +243,7 @@ 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

View File

@@ -1,6 +1,7 @@
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'),
@@ -8,9 +9,13 @@ 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 uploadMock = jest.fn() const releaseId = 100
const url = 'http://api.example.com' const url = 'http://api.example.com'
const deleteMock = jest.fn()
const listArtifactsMock = jest.fn()
const uploadMock = jest.fn()
jest.mock('fs', () => { jest.mock('fs', () => {
return { return {
readFileSync: () => fileContents, readFileSync: () => fileContents,
@@ -19,27 +24,184 @@ jest.mock('fs', () => {
}) })
describe('ArtifactUploader', () => { describe('ArtifactUploader', () => {
it('uploads artifacts', () => { beforeEach(() => {
const uploader = createUploader() deleteMock.mockClear()
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)
}) })
function createUploader(): GithubArtifactUploader { it('replaces no artifacts when previous asset list empty', async () => {
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 {
getByTag: jest.fn(),
create: jest.fn(), create: jest.fn(),
deleteArtifact: deleteMock,
getByTag: jest.fn(),
listArtifactsForRelease: listArtifactsMock,
listReleases: jest.fn(),
update: jest.fn(), update: jest.fn(),
uploadArtifact: uploadMock uploadArtifact: uploadMock
} }
}) })
return new GithubArtifactUploader(new MockReleases()) return new GithubArtifactUploader(new MockReleases(), replaces)
}
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({})
} }
}); });

View File

@@ -144,6 +144,17 @@ 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')

View File

@@ -6,6 +6,7 @@ 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,6 +33,9 @@ inputs:
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: ''

View File

@@ -1,13 +1,4 @@
"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 {
@@ -16,51 +7,62 @@ class Action {
this.releases = releases; this.releases = releases;
this.uploader = uploader; this.uploader = uploader;
} }
perform() { async perform() {
return __awaiter(this, void 0, void 0, function* () { const releaseResponse = await this.createOrUpdateRelease();
const uploadUrl = yield this.createOrUpdateRelease(); const releaseId = releaseResponse.id;
const artifacts = this.inputs.artifacts; const uploadUrl = releaseResponse.upload_url;
if (artifacts.length > 0) { const artifacts = this.inputs.artifacts;
yield this.uploader.uploadArtifacts(artifacts, uploadUrl); if (artifacts.length > 0) {
} await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl);
}); }
} }
createOrUpdateRelease() { async createOrUpdateRelease() {
return __awaiter(this, void 0, void 0, function* () { if (this.inputs.allowUpdates) {
if (this.inputs.allowUpdates) { try {
try { const getResponse = await this.releases.getByTag(this.inputs.tag);
const getResponse = yield this.releases.getByTag(this.inputs.tag); return await this.updateRelease(getResponse.data.id);
return yield this.updateRelease(getResponse.data.id); }
catch (error) {
if (this.noPublishedRelease(error)) {
return await this.updateDraftOrCreateRelease();
} }
catch (error) { else {
if (this.noRelease(error)) { throw error;
return yield this.createRelease();
}
else {
throw error;
}
} }
} }
else { }
return yield this.createRelease(); else {
} return await this.createRelease();
}); }
} }
createRelease() { async updateRelease(id) {
return __awaiter(this, void 0, void 0, function* () { 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);
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;
return response.data.upload_url;
});
} }
noRelease(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;
} }
updateRelease(id) { async updateDraftOrCreateRelease() {
return __awaiter(this, void 0, void 0, function* () { const draftReleaseId = await this.findMatchingDraftReleaseId();
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); if (draftReleaseId) {
return response.data.upload_url; return await this.updateRelease(draftReleaseId);
}); }
else {
return await this.createRelease();
}
}
async findMatchingDraftReleaseId() {
var _a;
const tag = this.inputs.tag;
const response = await this.releases.listReleases();
const releases = response.data;
const draftRelease = releases.find(release => release.draft && release.tag_name == tag);
return (_a = draftRelease) === null || _a === void 0 ? void 0 : _a.id;
}
async 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 response.data;
} }
} }
exports.Action = Action; exports.Action = Action;

View File

@@ -1,24 +1,55 @@
"use strict"; "use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { var __importStar = (this && this.__importStar) || function (mod) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } if (mod && mod.__esModule) return mod;
return new (P || (P = Promise))(function (resolve, reject) { var result = {};
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } result["default"] = mod;
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } return result;
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
class GithubArtifactUploader { class GithubArtifactUploader {
constructor(releases) { constructor(releases, replacesExistingArtifacts = true) {
this.releases = releases; this.releases = releases;
this.replacesExistingArtifacts = replacesExistingArtifacts;
} }
uploadArtifacts(artifacts, uploadUrl) { async uploadArtifacts(artifacts, releaseId, uploadUrl) {
return __awaiter(this, void 0, void 0, function* () { if (this.replacesExistingArtifacts) {
artifacts.forEach((artifact) => __awaiter(this, void 0, void 0, function* () { await this.deleteUpdatedArtifacts(artifacts, releaseId);
yield this.releases.uploadArtifact(uploadUrl, artifact.contentLength, artifact.contentType, artifact.readFile(), artifact.name); }
})); for (const artifact of artifacts) {
await this.uploadArtifact(artifact, uploadUrl);
}
}
async uploadArtifact(artifact, uploadUrl, 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}.`);
}
}
}
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;

View File

@@ -59,8 +59,12 @@ class CoreInputs {
return this.tag; return this.tag;
} }
get prerelease() { get prerelease() {
const draft = core.getInput('prerelease'); const preRelease = core.getInput('prerelease');
return draft == 'true'; return preRelease == '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');

View File

@@ -1,13 +1,4 @@
"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 = {};
@@ -24,17 +15,15 @@ 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");
function run() { async function run() {
return __awaiter(this, void 0, void 0, function* () { try {
try { const action = createAction();
const action = createAction(); await action.perform();
yield action.perform(); }
} catch (error) {
catch (error) { const errorMessage = new ErrorMessage_1.ErrorMessage(error);
const errorMessage = new ErrorMessage_1.ErrorMessage(error); core.setFailed(errorMessage.toString());
core.setFailed(errorMessage.toString()); }
}
});
} }
function createAction() { function createAction() {
const token = core.getInput('token'); const token = core.getInput('token');
@@ -43,7 +32,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); const uploader = new ArtifactUploader_1.GithubArtifactUploader(releases, inputs.replacesArtifacts);
return new Action_1.Action(inputs, releases, uploader); return new Action_1.Action(inputs, releases, uploader);
} }
run(); run();

View File

@@ -1,68 +1,71 @@
"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;
} }
create(tag, body, commitHash, draft, name, prerelease) { async create(tag, body, commitHash, draft, name, prerelease) {
return __awaiter(this, void 0, void 0, function* () { return this.git.repos.createRelease({
return this.git.repos.createRelease({ body: body,
body: body, name: name,
name: name, draft: draft,
draft: draft, owner: this.context.repo.owner,
owner: this.context.repo.owner, prerelease: prerelease,
prerelease: prerelease, repo: this.context.repo.repo,
repo: this.context.repo.repo, target_commitish: commitHash,
target_commitish: commitHash, tag_name: tag
tag_name: tag
});
}); });
} }
getByTag(tag) { async deleteArtifact(assetId) {
return __awaiter(this, void 0, void 0, function* () { return this.git.repos.deleteReleaseAsset({
return this.git.repos.getReleaseByTag({ asset_id: assetId,
owner: this.context.repo.owner, owner: this.context.repo.owner,
repo: this.context.repo.repo, repo: this.context.repo.repo
tag: tag
});
}); });
} }
update(id, tag, body, commitHash, draft, name, prerelease) { async listArtifactsForRelease(releaseId) {
return __awaiter(this, void 0, void 0, function* () { return this.git.repos.listAssetsForRelease({
return this.git.repos.updateRelease({ owner: this.context.repo.owner,
release_id: id, release_id: releaseId,
body: body, repo: this.context.repo.repo
name: name,
draft: draft,
owner: this.context.repo.owner,
prerelease: prerelease,
repo: this.context.repo.repo,
target_commitish: commitHash,
tag_name: tag
});
}); });
} }
uploadArtifact(assetUrl, contentLength, contentType, file, name) { async listReleases() {
return __awaiter(this, void 0, void 0, function* () { return this.git.repos.listReleases({
return this.git.repos.uploadReleaseAsset({ owner: this.context.repo.owner,
url: assetUrl, repo: this.context.repo.repo
headers: { });
"content-length": contentLength, }
"content-type": contentType async getByTag(tag) {
}, return this.git.repos.getReleaseByTag({
file: file, owner: this.context.repo.owner,
name: name repo: this.context.repo.repo,
}); tag: tag
});
}
async update(id, tag, body, commitHash, draft, name, prerelease) {
return this.git.repos.updateRelease({
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 uploadArtifact(assetUrl, contentLength, contentType, file, name) {
return this.git.repos.uploadReleaseAsset({
url: assetUrl,
headers: {
"content-length": contentLength,
"content-type": contentType
},
file: file,
name: name
}); });
} }
} }

56
node_modules/.yarn-integrity generated vendored
View File

@@ -1,5 +1,5 @@
{ {
"systemParams": "darwin-x64-72", "systemParams": "darwin-x64-79",
"modulesFolders": [ "modulesFolders": [
"node_modules" "node_modules"
], ],
@@ -11,14 +11,14 @@
"@actions/core@^1.0.0", "@actions/core@^1.0.0",
"@actions/github@^1.0.0", "@actions/github@^1.0.0",
"@types/glob@^7.1.1", "@types/glob@^7.1.1",
"@types/jest@^24.0.13", "@types/jest@^24.0.25",
"@types/node@^12.0.4", "@types/node@^12.0.4",
"add@^2.0.6", "add@^2.0.6",
"glob@^7.1.4", "glob@^7.1.4",
"global@^4.4.0", "global@^4.4.0",
"jest-circus@^24.7.1", "jest-circus@^24.7.1",
"jest@^24.8.0", "jest@^24.9.0",
"ts-jest@^24.0.2", "ts-jest@^24.2.0",
"typescript@^3.7.3" "typescript@^3.7.3"
], ],
"lockfileEntries": { "lockfileEntries": {
@@ -81,8 +81,7 @@
"@types/istanbul-lib-coverage@^2.0.0": "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff", "@types/istanbul-lib-coverage@^2.0.0": "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff",
"@types/istanbul-lib-report@*": "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c", "@types/istanbul-lib-report@*": "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c",
"@types/istanbul-reports@^1.1.1": "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a", "@types/istanbul-reports@^1.1.1": "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a",
"@types/jest-diff@*": "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89", "@types/jest@^24.0.25": "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f",
"@types/jest@^24.0.13": "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.18.tgz#9c7858d450c59e2164a8a9df0905fc5091944498",
"@types/minimatch@*": "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d", "@types/minimatch@*": "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d",
"@types/node@*": "https://registry.yarnpkg.com/@types/node/-/node-12.7.3.tgz#27b3f40addaf2f580459fdb405222685542f907a", "@types/node@*": "https://registry.yarnpkg.com/@types/node/-/node-12.7.3.tgz#27b3f40addaf2f580459fdb405222685542f907a",
"@types/node@^12.0.4": "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44", "@types/node@^12.0.4": "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44",
@@ -161,7 +160,7 @@
"color-name@1.1.3": "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25", "color-name@1.1.3": "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25",
"combined-stream@^1.0.6": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f", "combined-stream@^1.0.6": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f",
"combined-stream@~1.0.6": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f", "combined-stream@~1.0.6": "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f",
"commander@~2.20.0": "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422", "commander@~2.20.3": "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33",
"component-emitter@^1.2.1": "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0", "component-emitter@^1.2.1": "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0",
"concat-map@0.0.1": "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b", "concat-map@0.0.1": "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b",
"console-control-strings@^1.0.0": "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e", "console-control-strings@^1.0.0": "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e",
@@ -253,7 +252,7 @@
"graceful-fs@^4.1.15": "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02", "graceful-fs@^4.1.15": "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02",
"graceful-fs@^4.1.2": "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02", "graceful-fs@^4.1.2": "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02",
"growly@^1.3.0": "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081", "growly@^1.3.0": "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081",
"handlebars@^4.1.2": "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67", "handlebars@^4.1.2": "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482",
"har-schema@^2.0.0": "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92", "har-schema@^2.0.0": "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92",
"har-validator@~5.1.0": "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080", "har-validator@~5.1.0": "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080",
"has-flag@^3.0.0": "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd", "has-flag@^3.0.0": "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd",
@@ -325,6 +324,7 @@
"jest-circus@^24.7.1": "https://registry.yarnpkg.com/jest-circus/-/jest-circus-24.9.0.tgz#8a557683636807d537507eac02ba64c95b686485", "jest-circus@^24.7.1": "https://registry.yarnpkg.com/jest-circus/-/jest-circus-24.9.0.tgz#8a557683636807d537507eac02ba64c95b686485",
"jest-cli@^24.9.0": "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af", "jest-cli@^24.9.0": "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af",
"jest-config@^24.9.0": "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5", "jest-config@^24.9.0": "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5",
"jest-diff@^24.3.0": "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da",
"jest-diff@^24.9.0": "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da", "jest-diff@^24.9.0": "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da",
"jest-docblock@^24.3.0": "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2", "jest-docblock@^24.3.0": "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2",
"jest-each@^24.9.0": "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05", "jest-each@^24.9.0": "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05",
@@ -351,7 +351,7 @@
"jest-watcher@^24.9.0": "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b", "jest-watcher@^24.9.0": "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b",
"jest-worker@^24.6.0": "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5", "jest-worker@^24.6.0": "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5",
"jest-worker@^24.9.0": "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5", "jest-worker@^24.9.0": "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5",
"jest@^24.8.0": "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171", "jest@^24.9.0": "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171",
"js-tokens@^3.0.0 || ^4.0.0": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499", "js-tokens@^3.0.0 || ^4.0.0": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499",
"js-tokens@^4.0.0": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499", "js-tokens@^4.0.0": "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499",
"jsbn@~0.1.0": "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513", "jsbn@~0.1.0": "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513",
@@ -378,6 +378,7 @@
"load-json-file@^4.0.0": "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b", "load-json-file@^4.0.0": "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b",
"locate-path@^3.0.0": "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e", "locate-path@^3.0.0": "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e",
"lodash.get@^4.4.2": "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99", "lodash.get@^4.4.2": "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99",
"lodash.memoize@4.x": "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe",
"lodash.set@^4.3.2": "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23", "lodash.set@^4.3.2": "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23",
"lodash.sortby@^4.7.0": "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438", "lodash.sortby@^4.7.0": "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438",
"lodash.uniq@^4.5.0": "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773", "lodash.uniq@^4.5.0": "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773",
@@ -593,13 +594,13 @@
"tough-cookie@~2.4.3": "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781", "tough-cookie@~2.4.3": "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781",
"tr46@^1.0.1": "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09", "tr46@^1.0.1": "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09",
"trim-right@^1.0.1": "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003", "trim-right@^1.0.1": "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003",
"ts-jest@^24.0.2": "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.0.2.tgz#8dde6cece97c31c03e80e474c749753ffd27194d", "ts-jest@^24.2.0": "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.2.0.tgz#7abca28c2b4b0a1fdd715cd667d65d047ea4e768",
"tunnel-agent@^0.6.0": "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd", "tunnel-agent@^0.6.0": "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd",
"tweetnacl@^0.14.3": "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64", "tweetnacl@^0.14.3": "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64",
"tweetnacl@~0.14.0": "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64", "tweetnacl@~0.14.0": "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64",
"type-check@~0.3.2": "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72", "type-check@~0.3.2": "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72",
"typescript@^3.7.3": "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69", "typescript@^3.7.3": "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69",
"uglify-js@^3.1.4": "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5", "uglify-js@^3.1.4": "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a",
"union-value@^1.0.0": "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847", "union-value@^1.0.0": "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847",
"universal-user-agent@^2.0.3": "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.1.0.tgz#5abfbcc036a1ba490cb941f8fd68c46d3669e8e4", "universal-user-agent@^2.0.3": "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.1.0.tgz#5abfbcc036a1ba490cb941f8fd68c46d3669e8e4",
"universal-user-agent@^3.0.0": "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-3.0.0.tgz#4cc88d68097bffd7ac42e3b7c903e7481424b4b9", "universal-user-agent@^3.0.0": "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-3.0.0.tgz#4cc88d68097bffd7ac42e3b7c903e7481424b4b9",
@@ -645,11 +646,36 @@
"files": [], "files": [],
"artifacts": { "artifacts": {
"fsevents@1.2.9": [ "fsevents@1.2.9": [
"lib", "build",
"lib/binding", "build/.target.mk",
"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-v72-darwin-x64", "lib/binding/Release/node-v79-darwin-x64",
"lib/binding/Release/node-v72-darwin-x64/fse.node" "lib/binding/Release/node-v79-darwin-x64/fse.node"
] ]
} }
} }

View File

@@ -32,10 +32,10 @@
"global": "^4.4.0" "global": "^4.4.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.13", "@types/jest": "^24.0.25",
"jest": "^24.8.0", "jest": "^24.9.0",
"jest-circus": "^24.7.1", "jest-circus": "^24.7.1",
"ts-jest": "^24.0.2", "ts-jest": "^24.2.0",
"typescript": "^3.7.3" "typescript": "^3.7.3"
} }
} }

View File

@@ -1,5 +1,6 @@
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";
@@ -15,22 +16,24 @@ export class Action {
} }
async perform() { async perform() {
const uploadUrl = await this.createOrUpdateRelease() const releaseResponse = 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, uploadUrl) await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl)
} }
} }
private async createOrUpdateRelease(): Promise<string> { private async createOrUpdateRelease(): Promise<ReposCreateReleaseResponse> {
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)
return await this.updateRelease(getResponse.data.id) return await this.updateRelease(getResponse.data.id)
} catch (error) { } catch (error) {
if (this.noRelease(error)) { if (this.noPublishedRelease(error)) {
return await this.createRelease() return await this.updateDraftOrCreateRelease()
} else { } else {
throw error throw error
} }
@@ -40,25 +43,7 @@ export class Action {
} }
} }
private async createRelease(): Promise<string> { private async updateRelease(id: number): Promise<ReposCreateReleaseResponse> {
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 response.data.upload_url
}
private noRelease(error: any): boolean {
const errorMessage = new ErrorMessage(error)
return errorMessage.status == 404
}
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,
@@ -69,6 +54,42 @@ export class Action {
this.inputs.prerelease this.inputs.prerelease
) )
return response.data.upload_url return response.data
}
private noPublishedRelease(error: any): boolean {
const errorMessage = new ErrorMessage(error)
return errorMessage.status == 404
}
private async updateDraftOrCreateRelease(): Promise<ReposCreateReleaseResponse> {
const draftReleaseId = await this.findMatchingDraftReleaseId()
if (draftReleaseId) {
return await this.updateRelease(draftReleaseId)
} else {
return await this.createRelease()
}
}
private async findMatchingDraftReleaseId(): Promise<number | undefined> {
const tag = this.inputs.tag
const response = await this.releases.listReleases()
const releases = response.data
const draftRelease = releases.find(release => release.draft && release.tag_name == tag)
return draftRelease?.id
}
private async createRelease(): Promise<ReposCreateReleaseResponse> {
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 response.data
} }
} }

View File

@@ -1,24 +1,61 @@
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[], uploadUrl: string): Promise<void> uploadArtifacts(artifacts: Artifact[], releaseId: number, uploadUrl: string): Promise<void>
} }
export class GithubArtifactUploader implements ArtifactUploader { export class GithubArtifactUploader implements ArtifactUploader {
private releases: Releases constructor(
private releases: Releases,
constructor(releases: Releases) { private replacesExistingArtifacts: boolean = true,
this.releases = releases ) {
} }
async uploadArtifacts(artifacts: Artifact[], uploadUrl: string) { async uploadArtifacts(artifacts: Artifact[],
artifacts.forEach(async artifact => { releaseId: number,
uploadUrl: string): Promise<void> {
if (this.replacesExistingArtifacts) {
await this.deleteUpdatedArtifacts(artifacts, releaseId)
}
for (const artifact of artifacts) {
await this.uploadArtifact(artifact, uploadUrl)
}
}
private async uploadArtifact(artifact: Artifact, uploadUrl: string, retry = 3) {
try {
core.debug(`Uploading artifact ${artifact.name}...`)
await this.releases.uploadArtifact(uploadUrl, await this.releases.uploadArtifact(uploadUrl,
artifact.contentLength, artifact.contentLength,
artifact.contentType, artifact.contentType,
artifact.readFile(), artifact.readFile(),
artifact.name) 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)
}
}
} }
} }

View File

@@ -12,6 +12,7 @@ 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
} }
@@ -79,8 +80,13 @@ export class CoreInputs implements Inputs {
} }
get prerelease(): boolean { get prerelease(): boolean {
const draft = core.getInput('prerelease') const preRelease = core.getInput('prerelease')
return draft == 'true' return preRelease == 'true'
}
get replacesArtifacts(): boolean {
const replaces = core.getInput('replacesArtifacts')
return replaces == 'true'
} }
get tag(): string { get tag(): string {

View File

@@ -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) const uploader = new GithubArtifactUploader(releases, inputs.replacesArtifacts)
return new Action(inputs, releases, uploader) return new Action(inputs, releases, uploader)
} }

View File

@@ -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, ReposCreateReleaseResponse, ReposGetReleaseByTagResponse } from "@octokit/rest"; import { AnyResponse, Response, ReposDeleteReleaseAssetResponse, ReposListAssetsForReleaseResponse, ReposCreateReleaseResponse, ReposGetReleaseByTagResponse, ReposListReleasesResponse } from "@octokit/rest";
export interface Releases { export interface Releases {
create( create(
@@ -12,8 +12,14 @@ 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>>
update( update(
id: number, id: number,
tag: string, tag: string,
@@ -62,6 +68,33 @@ 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>> {
return this.git.repos.listReleases({
owner: this.context.repo.owner,
repo: this.context.repo.repo
})
}
async getByTag(tag: string): Promise<Response<ReposGetReleaseByTagResponse>> { async getByTag(tag: string): Promise<Response<ReposGetReleaseByTagResponse>> {
return this.git.repos.getReleaseByTag({ return this.git.repos.getReleaseByTag({
owner: this.context.repo.owner, owner: this.context.repo.owner,

View File

@@ -2,7 +2,7 @@
"compilerOptions": { "compilerOptions": {
/* Basic Options */ /* Basic Options */
// "incremental": true, /* Enable incremental compilation */ // "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "es2019", /* 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. */

View File

@@ -425,17 +425,12 @@
"@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*" "@types/istanbul-lib-report" "*"
"@types/jest-diff@*": "@types/jest@^24.0.25":
version "20.0.1" version "24.0.25"
resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f"
integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA== integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g==
"@types/jest@^24.0.13":
version "24.0.18"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.18.tgz#9c7858d450c59e2164a8a9df0905fc5091944498"
integrity sha512-jcDDXdjTcrQzdN06+TSVsPPqxvsZA/5QkYfIZlq1JMw7FdP5AZylbOc+6B/cuDurctRe+MziUMtQ3xQdrbjqyQ==
dependencies: dependencies:
"@types/jest-diff" "*" jest-diff "^24.3.0"
"@types/minimatch@*": "@types/minimatch@*":
version "3.0.3" version "3.0.3"
@@ -887,10 +882,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
commander@~2.20.0: commander@~2.20.3:
version "2.20.0" version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
component-emitter@^1.2.1: component-emitter@^1.2.1:
version "1.3.0" version "1.3.0"
@@ -1416,9 +1411,9 @@ growly@^1.3.0:
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
handlebars@^4.1.2: handlebars@^4.1.2:
version "4.1.2" version "4.5.3"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482"
integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==
dependencies: dependencies:
neo-async "^2.6.0" neo-async "^2.6.0"
optimist "^0.6.1" optimist "^0.6.1"
@@ -1872,7 +1867,7 @@ jest-config@^24.9.0:
pretty-format "^24.9.0" pretty-format "^24.9.0"
realpath-native "^1.1.0" realpath-native "^1.1.0"
jest-diff@^24.9.0: jest-diff@^24.3.0, jest-diff@^24.9.0:
version "24.9.0" version "24.9.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da"
integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==
@@ -2167,7 +2162,7 @@ jest-worker@^24.6.0, jest-worker@^24.9.0:
merge-stream "^2.0.0" merge-stream "^2.0.0"
supports-color "^6.1.0" supports-color "^6.1.0"
jest@^24.8.0: jest@^24.9.0:
version "24.9.0" version "24.9.0"
resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171"
integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw== integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==
@@ -2329,6 +2324,11 @@ lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.memoize@4.x:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=
lodash.set@^4.3.2: lodash.set@^4.3.2:
version "4.3.2" version "4.3.2"
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
@@ -3525,15 +3525,16 @@ trim-right@^1.0.1:
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
ts-jest@^24.0.2: ts-jest@^24.2.0:
version "24.0.2" version "24.2.0"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.0.2.tgz#8dde6cece97c31c03e80e474c749753ffd27194d" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.2.0.tgz#7abca28c2b4b0a1fdd715cd667d65d047ea4e768"
integrity sha512-h6ZCZiA1EQgjczxq+uGLXQlNgeg02WWJBbeT8j6nyIBRQdglqbvzDoHahTEIiS6Eor6x8mK6PfZ7brQ9Q6tzHw== integrity sha512-Yc+HLyldlIC9iIK8xEN7tV960Or56N49MDP7hubCZUeI7EbIOTsas6rXCMB4kQjLACJ7eDOF4xWEO5qumpKsag==
dependencies: dependencies:
bs-logger "0.x" bs-logger "0.x"
buffer-from "1.x" buffer-from "1.x"
fast-json-stable-stringify "2.x" fast-json-stable-stringify "2.x"
json5 "2.x" json5 "2.x"
lodash.memoize "4.x"
make-error "1.x" make-error "1.x"
mkdirp "0.x" mkdirp "0.x"
resolve "1.x" resolve "1.x"
@@ -3565,11 +3566,11 @@ typescript@^3.7.3:
integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==
uglify-js@^3.1.4: uglify-js@^3.1.4:
version "3.6.0" version "3.7.3"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a"
integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg==
dependencies: dependencies:
commander "~2.20.0" commander "~2.20.3"
source-map "~0.6.1" source-map "~0.6.1"
union-value@^1.0.0: union-value@^1.0.0: