1 Commits

Author SHA1 Message Date
Nick Cipollo
81af6e69fb Prepare 1.6.0 release
Some checks failed
PR Checks / check_pr (push) Has been cancelled
2020-03-02 22:24:25 -05:00
10 changed files with 226 additions and 267 deletions

2
.gitignore vendored
View File

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

View File

@@ -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'),
@@ -33,7 +32,6 @@ describe('ArtifactUploader', () => {
it('replaces all artifacts', async () => { it('replaces all artifacts', async () => {
mockDeleteSuccess() mockDeleteSuccess()
mockListWithAssets() mockListWithAssets()
mockUploadArtifact()
const uploader = createUploader(true) const uploader = createUploader(true)
await uploader.uploadArtifacts(artifacts, releaseId, url) await uploader.uploadArtifacts(artifacts, releaseId, url)
@@ -52,65 +50,6 @@ describe('ArtifactUploader', () => {
it('replaces no artifacts when previous asset list empty', async () => { it('replaces no artifacts when previous asset list empty', async () => {
mockDeleteSuccess() mockDeleteSuccess()
mockListWithoutAssets() 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) const uploader = createUploader(true)
await uploader.uploadArtifacts(artifacts, releaseId, url) await uploader.uploadArtifacts(artifacts, releaseId, url)
@@ -127,7 +66,6 @@ describe('ArtifactUploader', () => {
it('throws error from replace', async () => { it('throws error from replace', async () => {
mockDeleteError() mockDeleteError()
mockListWithAssets() mockListWithAssets()
mockUploadArtifact()
const uploader = createUploader(true) const uploader = createUploader(true)
expect.hasAssertions() expect.hasAssertions()
@@ -141,7 +79,6 @@ describe('ArtifactUploader', () => {
it('updates all artifacts, delete none', async () => { it('updates all artifacts, delete none', async () => {
mockDeleteError() mockDeleteError()
mockListWithAssets() mockListWithAssets()
mockUploadArtifact()
const uploader = createUploader(false) const uploader = createUploader(false)
await uploader.uploadArtifacts(artifacts, releaseId, url) await uploader.uploadArtifacts(artifacts, releaseId, url)
@@ -156,6 +93,7 @@ describe('ArtifactUploader', () => {
}) })
function createUploader(replaces: boolean): GithubArtifactUploader { function createUploader(replaces: boolean): GithubArtifactUploader {
uploadMock.mockResolvedValue({})
const MockReleases = jest.fn<Releases, any>(() => { const MockReleases = jest.fn<Releases, any>(() => {
return { return {
create: jest.fn(), create: jest.fn(),
@@ -196,12 +134,4 @@ describe('ArtifactUploader', () => {
function mockListWithoutAssets() { function mockListWithoutAssets() {
listArtifactsMock.mockResolvedValue({ data: [] }) 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

@@ -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:

View File

@@ -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,74 @@ 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 releaseResponse = yield this.createOrUpdateRelease();
const uploadUrl = releaseResponse.upload_url; const releaseId = releaseResponse.id;
const artifacts = this.inputs.artifacts; const uploadUrl = releaseResponse.upload_url;
if (artifacts.length > 0) { const artifacts = this.inputs.artifacts;
await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl); if (artifacts.length > 0) {
} yield 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;
});
} }
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;
});
} }
} }
exports.Action = Action; exports.Action = Action;

View File

@@ -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,43 @@ 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, replacesExistingArtifacts) {
this.replacesExistingArtifacts = true;
this.releases = releases; this.releases = releases;
this.replacesExistingArtifacts = replacesExistingArtifacts; this.replacesExistingArtifacts = replacesExistingArtifacts;
} }
async uploadArtifacts(artifacts, releaseId, uploadUrl) { uploadArtifacts(artifacts, releaseId, uploadUrl) {
if (this.replacesExistingArtifacts) { return __awaiter(this, void 0, void 0, function* () {
await this.deleteUpdatedArtifacts(artifacts, releaseId); if (this.replacesExistingArtifacts) {
} yield this.deleteUpdatedArtifacts(artifacts, releaseId);
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 { for (const artifact of artifacts) {
core.warning(`Failed to upload artifact ${artifact.name}. ${error.message}.`); try {
yield this.releases.uploadArtifact(uploadUrl, artifact.contentLength, artifact.contentType, artifact.readFile(), artifact.name);
}
catch (error) {
const message = `Failed to upload artifact ${artifact.name}. Does it already exist?`;
core.warning(message);
}
} }
} return Promise.resolve();
}
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]; deleteUpdatedArtifacts(artifacts, releaseId) {
if (asset) { return __awaiter(this, void 0, void 0, function* () {
core.debug(`Deleting existing artifact ${artifact.name}...`); const response = yield this.releases.listArtifactsForRelease(releaseId);
await this.releases.deleteArtifact(asset.id); const releaseAssets = response.data;
const assetByName = new Map();
releaseAssets.forEach(asset => {
assetByName[asset.name] = asset;
});
for (const artifact of artifacts) {
const asset = assetByName[artifact.name];
if (asset) {
yield this.releases.deleteArtifact(asset.id);
}
} }
} });
} }
} }
exports.GithubArtifactUploader = GithubArtifactUploader; exports.GithubArtifactUploader = GithubArtifactUploader;

View File

@@ -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');

View File

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

35
node_modules/.yarn-integrity generated vendored
View File

@@ -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"
] ]
} }
} }

View File

@@ -2,58 +2,53 @@ 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"; import { ReposListAssetsForReleaseResponseItem } from "@octokit/rest";
import { ErrorMessage } from './ErrorMessage';
export interface ArtifactUploader { export interface ArtifactUploader {
uploadArtifacts(artifacts: Artifact[], releaseId: number, uploadUrl: string): Promise<void> uploadArtifacts(artifacts: Artifact[], releaseId: number, 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
private replacesExistingArtifacts: boolean = true,
) { constructor(releases: Releases, replacesExistingArtifacts: boolean) {
this.releases = releases
this.replacesExistingArtifacts = replacesExistingArtifacts
} }
async uploadArtifacts(artifacts: Artifact[], async uploadArtifacts(artifacts: Artifact[],
releaseId: number, releaseId: number,
uploadUrl: string): Promise<void> { uploadUrl: string): Promise<void> {
if (this.replacesExistingArtifacts) { if(this.replacesExistingArtifacts) {
await this.deleteUpdatedArtifacts(artifacts, releaseId) await this.deleteUpdatedArtifacts(artifacts, releaseId)
} }
for (const artifact of artifacts) {
await this.uploadArtifact(artifact, uploadUrl)
}
}
private async uploadArtifact(artifact: Artifact, uploadUrl: string, retry = 3) { for (const artifact of artifacts) {
try { 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) {
} catch (error) { const message = `Failed to upload artifact ${artifact.name}. Does it already exist?`
if (error.status >= 500 && retry > 0) { core.warning(message)
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}.`)
} }
} }
return Promise.resolve()
} }
private async deleteUpdatedArtifacts(artifacts: Artifact[], releaseId: number): Promise<void> { async deleteUpdatedArtifacts(artifacts: Artifact[], releaseId: number) {
const response = await this.releases.listArtifactsForRelease(releaseId) const response = await this.releases.listArtifactsForRelease(releaseId)
const releaseAssets = response.data const releaseAssets = response.data
const assetByName: Record<string, ReposListAssetsForReleaseResponseItem> = {} const assetByName = new Map<string, ReposListAssetsForReleaseResponseItem>()
releaseAssets.forEach(asset => { releaseAssets.forEach(asset => {
assetByName[asset.name] = asset assetByName[asset.name] = asset
}); });
for (const artifact of artifacts) { for (const artifact of artifacts) {
const asset = assetByName[artifact.name] const asset = assetByName[artifact.name]
if (asset) { if (asset) {
core.debug(`Deleting existing artifact ${artifact.name}...`)
await this.releases.deleteArtifact(asset.id) await this.releases.deleteArtifact(asset.id)
} }
} }

View File

@@ -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. */