Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retry on artifact already exists #548

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions dist/merge/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129842,23 +129842,48 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.uploadArtifact = void 0;
const core = __importStar(__nccwpck_require__(42186));
const github = __importStar(__nccwpck_require__(95438));
const artifact_1 = __importDefault(__nccwpck_require__(79450));
function uploadArtifact(artifactName, filesToUpload, rootDirectory, options) {
const artifact_1 = __importStar(__nccwpck_require__(79450));
function deleteArtifactIfExists(artifactName) {
return __awaiter(this, void 0, void 0, function* () {
const uploadResponse = yield artifact_1.default.uploadArtifact(artifactName, filesToUpload, rootDirectory, options);
core.info(`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`);
core.setOutput('artifact-id', uploadResponse.id);
const repository = github.context.repo;
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`;
core.info(`Artifact download URL: ${artifactURL}`);
core.setOutput('artifact-url', artifactURL);
try {
yield artifact_1.default.deleteArtifact(artifactName);
}
catch (error) {
if (error instanceof artifact_1.ArtifactNotFoundError) {
core.debug(`Skipping deletion of '${artifactName}', it does not exist`);
return;
}
// Best effort, we don't want to fail the action if this fails
core.debug(`Unable to delete artifact: ${error.message}`);
}
});
}
function uploadArtifact(artifactName, filesToUpload, rootDirectory, options, overwrite = false, retryAttempts = 3) {
return __awaiter(this, void 0, void 0, function* () {
try {
if (overwrite) {
yield deleteArtifactIfExists(artifactName);
}
const uploadResponse = yield artifact_1.default.uploadArtifact(artifactName, filesToUpload, rootDirectory, options);
core.info(`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`);
core.setOutput('artifact-id', uploadResponse.id);
const repository = github.context.repo;
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`;
core.info(`Artifact download URL: ${artifactURL}`);
core.setOutput('artifact-url', artifactURL);
}
catch (error) {
if (error instanceof artifact_1.InvalidResponseError &&
error.message.includes('Conflict: an artifact with this name already exists on the workflow run') &&
overwrite &&
retryAttempts) {
uploadArtifact(artifactName, filesToUpload, rootDirectory, options, overwrite, retryAttempts - 1);
}
}
});
}
exports.uploadArtifact = uploadArtifact;
Expand Down
70 changes: 38 additions & 32 deletions dist/upload/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129600,23 +129600,48 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.uploadArtifact = void 0;
const core = __importStar(__nccwpck_require__(42186));
const github = __importStar(__nccwpck_require__(95438));
const artifact_1 = __importDefault(__nccwpck_require__(79450));
function uploadArtifact(artifactName, filesToUpload, rootDirectory, options) {
const artifact_1 = __importStar(__nccwpck_require__(79450));
function deleteArtifactIfExists(artifactName) {
return __awaiter(this, void 0, void 0, function* () {
const uploadResponse = yield artifact_1.default.uploadArtifact(artifactName, filesToUpload, rootDirectory, options);
core.info(`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`);
core.setOutput('artifact-id', uploadResponse.id);
const repository = github.context.repo;
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`;
core.info(`Artifact download URL: ${artifactURL}`);
core.setOutput('artifact-url', artifactURL);
try {
yield artifact_1.default.deleteArtifact(artifactName);
}
catch (error) {
if (error instanceof artifact_1.ArtifactNotFoundError) {
core.debug(`Skipping deletion of '${artifactName}', it does not exist`);
return;
}
// Best effort, we don't want to fail the action if this fails
core.debug(`Unable to delete artifact: ${error.message}`);
}
});
}
function uploadArtifact(artifactName, filesToUpload, rootDirectory, options, overwrite = false, retryAttempts = 3) {
return __awaiter(this, void 0, void 0, function* () {
try {
if (overwrite) {
yield deleteArtifactIfExists(artifactName);
}
const uploadResponse = yield artifact_1.default.uploadArtifact(artifactName, filesToUpload, rootDirectory, options);
core.info(`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`);
core.setOutput('artifact-id', uploadResponse.id);
const repository = github.context.repo;
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`;
core.info(`Artifact download URL: ${artifactURL}`);
core.setOutput('artifact-url', artifactURL);
}
catch (error) {
if (error instanceof artifact_1.InvalidResponseError &&
error.message.includes('Conflict: an artifact with this name already exists on the workflow run') &&
overwrite &&
retryAttempts) {
uploadArtifact(artifactName, filesToUpload, rootDirectory, options, overwrite, retryAttempts - 1);
}
}
});
}
exports.uploadArtifact = uploadArtifact;
Expand Down Expand Up @@ -129812,26 +129837,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.run = void 0;
const core = __importStar(__nccwpck_require__(42186));
const artifact_1 = __importStar(__nccwpck_require__(79450));
const search_1 = __nccwpck_require__(8725);
const input_helper_1 = __nccwpck_require__(67022);
const constants_1 = __nccwpck_require__(86154);
const upload_artifact_1 = __nccwpck_require__(56680);
function deleteArtifactIfExists(artifactName) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield artifact_1.default.deleteArtifact(artifactName);
}
catch (error) {
if (error instanceof artifact_1.ArtifactNotFoundError) {
core.debug(`Skipping deletion of '${artifactName}', it does not exist`);
return;
}
// Best effort, we don't want to fail the action if this fails
core.debug(`Unable to delete artifact: ${error.message}`);
}
});
}
function run() {
return __awaiter(this, void 0, void 0, function* () {
const inputs = (0, input_helper_1.getInputs)();
Expand All @@ -129857,17 +129866,14 @@ function run() {
const s = searchResult.filesToUpload.length === 1 ? '' : 's';
core.info(`With the provided path, there will be ${searchResult.filesToUpload.length} file${s} uploaded`);
core.debug(`Root artifact directory is ${searchResult.rootDirectory}`);
if (inputs.overwrite) {
yield deleteArtifactIfExists(inputs.artifactName);
}
const options = {};
if (inputs.retentionDays) {
options.retentionDays = inputs.retentionDays;
}
if (typeof inputs.compressionLevel !== 'undefined') {
options.compressionLevel = inputs.compressionLevel;
}
yield (0, upload_artifact_1.uploadArtifact)(inputs.artifactName, searchResult.filesToUpload, searchResult.rootDirectory, options);
yield (0, upload_artifact_1.uploadArtifact)(inputs.artifactName, searchResult.filesToUpload, searchResult.rootDirectory, options, inputs.overwrite);
}
});
}
Expand Down
77 changes: 61 additions & 16 deletions src/shared/upload-artifact.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,73 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import artifact, {UploadArtifactOptions} from '@actions/artifact'
import artifact, {
UploadArtifactOptions,
ArtifactNotFoundError,
InvalidResponseError
} from '@actions/artifact'
import {UploadInputs} from '../upload/upload-inputs'
import {MergeInputs} from '../merge/merge-inputs'

async function deleteArtifactIfExists(artifactName: string): Promise<void> {
try {
await artifact.deleteArtifact(artifactName)
} catch (error) {
if (error instanceof ArtifactNotFoundError) {
core.debug(`Skipping deletion of '${artifactName}', it does not exist`)
return
}

// Best effort, we don't want to fail the action if this fails
core.debug(`Unable to delete artifact: ${(error as Error).message}`)
}
}

export async function uploadArtifact(
artifactName: string,
filesToUpload: string[],
rootDirectory: string,
options: UploadArtifactOptions
options: UploadArtifactOptions,
overwrite: boolean = false,
retryAttempts: number = 3
) {
const uploadResponse = await artifact.uploadArtifact(
artifactName,
filesToUpload,
rootDirectory,
options
)
try {
if (overwrite) {
await deleteArtifactIfExists(artifactName)
}
const uploadResponse = await artifact.uploadArtifact(
artifactName,
filesToUpload,
rootDirectory,
options
)

core.info(
`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`
)
core.setOutput('artifact-id', uploadResponse.id)
core.info(
`Artifact ${artifactName} has been successfully uploaded! Final size is ${uploadResponse.size} bytes. Artifact ID is ${uploadResponse.id}`
)
core.setOutput('artifact-id', uploadResponse.id)

const repository = github.context.repo
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`
const repository = github.context.repo
const artifactURL = `${github.context.serverUrl}/${repository.owner}/${repository.repo}/actions/runs/${github.context.runId}/artifacts/${uploadResponse.id}`

core.info(`Artifact download URL: ${artifactURL}`)
core.setOutput('artifact-url', artifactURL)
core.info(`Artifact download URL: ${artifactURL}`)
core.setOutput('artifact-url', artifactURL)
} catch (error) {
if (
error instanceof InvalidResponseError &&
error.message.includes(
'Conflict: an artifact with this name already exists on the workflow run'
) &&
overwrite &&
retryAttempts
) {
uploadArtifact(
artifactName,
filesToUpload,
rootDirectory,
options,
overwrite,
retryAttempts - 1
)
}
}
}
26 changes: 3 additions & 23 deletions src/upload/upload-artifact.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import * as core from '@actions/core'
import artifact, {
UploadArtifactOptions,
ArtifactNotFoundError
} from '@actions/artifact'
import {UploadArtifactOptions} from '@actions/artifact'
import {findFilesToUpload} from '../shared/search'
import {getInputs} from './input-helper'
import {NoFileOptions} from './constants'
import {uploadArtifact} from '../shared/upload-artifact'

async function deleteArtifactIfExists(artifactName: string): Promise<void> {
try {
await artifact.deleteArtifact(artifactName)
} catch (error) {
if (error instanceof ArtifactNotFoundError) {
core.debug(`Skipping deletion of '${artifactName}', it does not exist`)
return
}

// Best effort, we don't want to fail the action if this fails
core.debug(`Unable to delete artifact: ${(error as Error).message}`)
}
}

export async function run(): Promise<void> {
const inputs = getInputs()
const searchResult = await findFilesToUpload(inputs.searchPath)
Expand Down Expand Up @@ -54,10 +37,6 @@ export async function run(): Promise<void> {
)
core.debug(`Root artifact directory is ${searchResult.rootDirectory}`)

if (inputs.overwrite) {
await deleteArtifactIfExists(inputs.artifactName)
}

const options: UploadArtifactOptions = {}
if (inputs.retentionDays) {
options.retentionDays = inputs.retentionDays
Expand All @@ -71,7 +50,8 @@ export async function run(): Promise<void> {
inputs.artifactName,
searchResult.filesToUpload,
searchResult.rootDirectory,
options
options,
inputs.overwrite
)
}
}