Add retry for uploading artifact (#13)

This commit is contained in:
Nick Cipollo
2020-03-05 11:39:02 -05:00
committed by GitHub
parent d57d57cad2
commit 2ea88b1f32
8 changed files with 238 additions and 222 deletions

View File

@@ -1,13 +1,4 @@
"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 });
const ErrorMessage_1 = require("./ErrorMessage");
class Action {
@@ -16,74 +7,62 @@ class Action {
this.releases = releases;
this.uploader = uploader;
}
perform() {
return __awaiter(this, void 0, void 0, function* () {
const releaseResponse = yield this.createOrUpdateRelease();
const releaseId = releaseResponse.id;
const uploadUrl = releaseResponse.upload_url;
const artifacts = this.inputs.artifacts;
if (artifacts.length > 0) {
yield this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl);
}
});
async perform() {
const releaseResponse = await this.createOrUpdateRelease();
const releaseId = releaseResponse.id;
const uploadUrl = releaseResponse.upload_url;
const artifacts = this.inputs.artifacts;
if (artifacts.length > 0) {
await this.uploader.uploadArtifacts(artifacts, releaseId, uploadUrl);
}
}
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);
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();
}
catch (error) {
if (this.noPublishedRelease(error)) {
return yield this.updateDraftOrCreateRelease();
}
else {
throw error;
}
else {
throw error;
}
}
else {
return yield this.createRelease();
}
});
}
else {
return await this.createRelease();
}
}
updateRelease(id) {
return __awaiter(this, void 0, void 0, function* () {
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;
});
async 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 response.data;
}
noPublishedRelease(error) {
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
return errorMessage.status == 404;
}
updateDraftOrCreateRelease() {
return __awaiter(this, void 0, void 0, function* () {
const draftReleaseId = yield this.findMatchingDraftReleaseId();
if (draftReleaseId) {
return yield this.updateRelease(draftReleaseId);
}
else {
return yield this.createRelease();
}
});
async updateDraftOrCreateRelease() {
const draftReleaseId = await this.findMatchingDraftReleaseId();
if (draftReleaseId) {
return await this.updateRelease(draftReleaseId);
}
else {
return await this.createRelease();
}
}
findMatchingDraftReleaseId() {
async findMatchingDraftReleaseId() {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const tag = this.inputs.tag;
const response = yield 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;
});
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;
}
createRelease() {
return __awaiter(this, void 0, void 0, function* () {
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;
});
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;

View File

@@ -1,13 +1,4 @@
"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) {
if (mod && mod.__esModule) return mod;
var result = {};
@@ -18,43 +9,47 @@ var __importStar = (this && this.__importStar) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
class GithubArtifactUploader {
constructor(releases, replacesExistingArtifacts) {
this.replacesExistingArtifacts = true;
constructor(releases, replacesExistingArtifacts = true) {
this.releases = releases;
this.replacesExistingArtifacts = replacesExistingArtifacts;
}
uploadArtifacts(artifacts, releaseId, uploadUrl) {
return __awaiter(this, void 0, void 0, function* () {
if (this.replacesExistingArtifacts) {
yield this.deleteUpdatedArtifacts(artifacts, releaseId);
}
for (const artifact of artifacts) {
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 uploadArtifacts(artifacts, releaseId, uploadUrl) {
if (this.replacesExistingArtifacts) {
await this.deleteUpdatedArtifacts(artifacts, releaseId);
}
for (const artifact of artifacts) {
await this.uploadArtifact(artifact, uploadUrl);
}
}
deleteUpdatedArtifacts(artifacts, releaseId) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield this.releases.listArtifactsForRelease(releaseId);
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);
}
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 exist artifact ${artifact.name}...`);
await this.releases.deleteArtifact(asset.id);
}
}
}
}
exports.GithubArtifactUploader = GithubArtifactUploader;

View File

@@ -1,13 +1,4 @@
"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) {
if (mod && mod.__esModule) return mod;
var result = {};
@@ -24,17 +15,15 @@ const Action_1 = require("./Action");
const ArtifactUploader_1 = require("./ArtifactUploader");
const ArtifactGlobber_1 = require("./ArtifactGlobber");
const ErrorMessage_1 = require("./ErrorMessage");
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const action = createAction();
yield action.perform();
}
catch (error) {
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
core.setFailed(errorMessage.toString());
}
});
async function run() {
try {
const action = createAction();
await action.perform();
}
catch (error) {
const errorMessage = new ErrorMessage_1.ErrorMessage(error);
core.setFailed(errorMessage.toString());
}
}
function createAction() {
const token = core.getInput('token');

View File

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