Add some dependencies for uploading artifacts
This commit is contained in:
parent
1d05ad7576
commit
0cbd4b56d3
111 changed files with 9299 additions and 3597 deletions
41
node_modules/@actions/artifact/lib/internal/artifact-client.d.ts
generated
vendored
Normal file
41
node_modules/@actions/artifact/lib/internal/artifact-client.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { UploadResponse } from './upload-response';
|
||||
import { UploadOptions } from './upload-options';
|
||||
import { DownloadOptions } from './download-options';
|
||||
import { DownloadResponse } from './download-response';
|
||||
export interface ArtifactClient {
|
||||
/**
|
||||
* Uploads an artifact
|
||||
*
|
||||
* @param name the name of the artifact, required
|
||||
* @param files a list of absolute or relative paths that denote what files should be uploaded
|
||||
* @param rootDirectory an absolute or relative file path that denotes the root parent directory of the files being uploaded
|
||||
* @param options extra options for customizing the upload behavior
|
||||
* @returns single UploadInfo object
|
||||
*/
|
||||
uploadArtifact(name: string, files: string[], rootDirectory: string, options?: UploadOptions): Promise<UploadResponse>;
|
||||
/**
|
||||
* Downloads a single artifact associated with a run
|
||||
*
|
||||
* @param name the name of the artifact being downloaded
|
||||
* @param path optional path that denotes where the artifact will be downloaded to
|
||||
* @param options extra options that allow for the customization of the download behavior
|
||||
*/
|
||||
downloadArtifact(name: string, path?: string, options?: DownloadOptions): Promise<DownloadResponse>;
|
||||
/**
|
||||
* Downloads all artifacts associated with a run. Because there are multiple artifacts being downloaded, a folder will be created for each one in the specified or default directory
|
||||
* @param path optional path that denotes where the artifacts will be downloaded to
|
||||
*/
|
||||
downloadAllArtifacts(path?: string): Promise<DownloadResponse[]>;
|
||||
}
|
||||
export declare class DefaultArtifactClient implements ArtifactClient {
|
||||
/**
|
||||
* Constructs a DefaultArtifactClient
|
||||
*/
|
||||
static create(): DefaultArtifactClient;
|
||||
/**
|
||||
* Uploads an artifact
|
||||
*/
|
||||
uploadArtifact(name: string, files: string[], rootDirectory: string, options?: UploadOptions | undefined): Promise<UploadResponse>;
|
||||
downloadArtifact(name: string, path?: string | undefined, options?: DownloadOptions | undefined): Promise<DownloadResponse>;
|
||||
downloadAllArtifacts(path?: string | undefined): Promise<DownloadResponse[]>;
|
||||
}
|
||||
149
node_modules/@actions/artifact/lib/internal/artifact-client.js
generated
vendored
Normal file
149
node_modules/@actions/artifact/lib/internal/artifact-client.js
generated
vendored
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
"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 = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const upload_specification_1 = require("./upload-specification");
|
||||
const upload_http_client_1 = require("./upload-http-client");
|
||||
const utils_1 = require("./utils");
|
||||
const download_http_client_1 = require("./download-http-client");
|
||||
const download_specification_1 = require("./download-specification");
|
||||
const config_variables_1 = require("./config-variables");
|
||||
const path_1 = require("path");
|
||||
class DefaultArtifactClient {
|
||||
/**
|
||||
* Constructs a DefaultArtifactClient
|
||||
*/
|
||||
static create() {
|
||||
return new DefaultArtifactClient();
|
||||
}
|
||||
/**
|
||||
* Uploads an artifact
|
||||
*/
|
||||
uploadArtifact(name, files, rootDirectory, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
utils_1.checkArtifactName(name);
|
||||
// Get specification for the files being uploaded
|
||||
const uploadSpecification = upload_specification_1.getUploadSpecification(name, rootDirectory, files);
|
||||
const uploadResponse = {
|
||||
artifactName: name,
|
||||
artifactItems: [],
|
||||
size: 0,
|
||||
failedItems: []
|
||||
};
|
||||
const uploadHttpClient = new upload_http_client_1.UploadHttpClient();
|
||||
if (uploadSpecification.length === 0) {
|
||||
core.warning(`No files found that can be uploaded`);
|
||||
}
|
||||
else {
|
||||
// Create an entry for the artifact in the file container
|
||||
const response = yield uploadHttpClient.createArtifactInFileContainer(name, options);
|
||||
if (!response.fileContainerResourceUrl) {
|
||||
core.debug(response.toString());
|
||||
throw new Error('No URL provided by the Artifact Service to upload an artifact to');
|
||||
}
|
||||
core.debug(`Upload Resource URL: ${response.fileContainerResourceUrl}`);
|
||||
// Upload each of the files that were found concurrently
|
||||
const uploadResult = yield uploadHttpClient.uploadArtifactToFileContainer(response.fileContainerResourceUrl, uploadSpecification, options);
|
||||
// Update the size of the artifact to indicate we are done uploading
|
||||
// The uncompressed size is used for display when downloading a zip of the artifact from the UI
|
||||
yield uploadHttpClient.patchArtifactSize(uploadResult.totalSize, name);
|
||||
core.info(`Finished uploading artifact ${name}. Reported size is ${uploadResult.uploadSize} bytes. There were ${uploadResult.failedItems.length} items that failed to upload`);
|
||||
uploadResponse.artifactItems = uploadSpecification.map(item => item.absoluteFilePath);
|
||||
uploadResponse.size = uploadResult.uploadSize;
|
||||
uploadResponse.failedItems = uploadResult.failedItems;
|
||||
}
|
||||
return uploadResponse;
|
||||
});
|
||||
}
|
||||
downloadArtifact(name, path, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const downloadHttpClient = new download_http_client_1.DownloadHttpClient();
|
||||
const artifacts = yield downloadHttpClient.listArtifacts();
|
||||
if (artifacts.count === 0) {
|
||||
throw new Error(`Unable to find any artifacts for the associated workflow`);
|
||||
}
|
||||
const artifactToDownload = artifacts.value.find(artifact => {
|
||||
return artifact.name === name;
|
||||
});
|
||||
if (!artifactToDownload) {
|
||||
throw new Error(`Unable to find an artifact with the name: ${name}`);
|
||||
}
|
||||
const items = yield downloadHttpClient.getContainerItems(artifactToDownload.name, artifactToDownload.fileContainerResourceUrl);
|
||||
if (!path) {
|
||||
path = config_variables_1.getWorkSpaceDirectory();
|
||||
}
|
||||
path = path_1.normalize(path);
|
||||
path = path_1.resolve(path);
|
||||
// During upload, empty directories are rejected by the remote server so there should be no artifacts that consist of only empty directories
|
||||
const downloadSpecification = download_specification_1.getDownloadSpecification(name, items.value, path, (options === null || options === void 0 ? void 0 : options.createArtifactFolder) || false);
|
||||
if (downloadSpecification.filesToDownload.length === 0) {
|
||||
core.info(`No downloadable files were found for the artifact: ${artifactToDownload.name}`);
|
||||
}
|
||||
else {
|
||||
// Create all necessary directories recursively before starting any download
|
||||
yield utils_1.createDirectoriesForArtifact(downloadSpecification.directoryStructure);
|
||||
core.info('Directory structure has been setup for the artifact');
|
||||
yield utils_1.createEmptyFilesForArtifact(downloadSpecification.emptyFilesToCreate);
|
||||
yield downloadHttpClient.downloadSingleArtifact(downloadSpecification.filesToDownload);
|
||||
}
|
||||
return {
|
||||
artifactName: name,
|
||||
downloadPath: downloadSpecification.rootDownloadLocation
|
||||
};
|
||||
});
|
||||
}
|
||||
downloadAllArtifacts(path) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const downloadHttpClient = new download_http_client_1.DownloadHttpClient();
|
||||
const response = [];
|
||||
const artifacts = yield downloadHttpClient.listArtifacts();
|
||||
if (artifacts.count === 0) {
|
||||
core.info('Unable to find any artifacts for the associated workflow');
|
||||
return response;
|
||||
}
|
||||
if (!path) {
|
||||
path = config_variables_1.getWorkSpaceDirectory();
|
||||
}
|
||||
path = path_1.normalize(path);
|
||||
path = path_1.resolve(path);
|
||||
let downloadedArtifacts = 0;
|
||||
while (downloadedArtifacts < artifacts.count) {
|
||||
const currentArtifactToDownload = artifacts.value[downloadedArtifacts];
|
||||
downloadedArtifacts += 1;
|
||||
// Get container entries for the specific artifact
|
||||
const items = yield downloadHttpClient.getContainerItems(currentArtifactToDownload.name, currentArtifactToDownload.fileContainerResourceUrl);
|
||||
const downloadSpecification = download_specification_1.getDownloadSpecification(currentArtifactToDownload.name, items.value, path, true);
|
||||
if (downloadSpecification.filesToDownload.length === 0) {
|
||||
core.info(`No downloadable files were found for any artifact ${currentArtifactToDownload.name}`);
|
||||
}
|
||||
else {
|
||||
yield utils_1.createDirectoriesForArtifact(downloadSpecification.directoryStructure);
|
||||
yield utils_1.createEmptyFilesForArtifact(downloadSpecification.emptyFilesToCreate);
|
||||
yield downloadHttpClient.downloadSingleArtifact(downloadSpecification.filesToDownload);
|
||||
}
|
||||
response.push({
|
||||
artifactName: currentArtifactToDownload.name,
|
||||
downloadPath: downloadSpecification.rootDownloadLocation
|
||||
});
|
||||
}
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.DefaultArtifactClient = DefaultArtifactClient;
|
||||
//# sourceMappingURL=artifact-client.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/artifact-client.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/artifact-client.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"artifact-client.js","sourceRoot":"","sources":["../../src/internal/artifact-client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,oDAAqC;AACrC,iEAG+B;AAC/B,6DAAqD;AAKrD,mCAIgB;AAChB,iEAAyD;AACzD,qEAAiE;AACjE,yDAAwD;AACxD,+BAAuC;AAuCvC,MAAa,qBAAqB;IAChC;;OAEG;IACH,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,qBAAqB,EAAE,CAAA;IACpC,CAAC;IAED;;OAEG;IACG,cAAc,CAClB,IAAY,EACZ,KAAe,EACf,aAAqB,EACrB,OAAmC;;YAEnC,yBAAiB,CAAC,IAAI,CAAC,CAAA;YAEvB,iDAAiD;YACjD,MAAM,mBAAmB,GAA0B,6CAAsB,CACvE,IAAI,EACJ,aAAa,EACb,KAAK,CACN,CAAA;YACD,MAAM,cAAc,GAAmB;gBACrC,YAAY,EAAE,IAAI;gBAClB,aAAa,EAAE,EAAE;gBACjB,IAAI,EAAE,CAAC;gBACP,WAAW,EAAE,EAAE;aAChB,CAAA;YAED,MAAM,gBAAgB,GAAG,IAAI,qCAAgB,EAAE,CAAA;YAE/C,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE;gBACpC,IAAI,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAA;aACpD;iBAAM;gBACL,yDAAyD;gBACzD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,6BAA6B,CACnE,IAAI,EACJ,OAAO,CACR,CAAA;gBACD,IAAI,CAAC,QAAQ,CAAC,wBAAwB,EAAE;oBACtC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;oBAC/B,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAA;iBACF;gBACD,IAAI,CAAC,KAAK,CAAC,wBAAwB,QAAQ,CAAC,wBAAwB,EAAE,CAAC,CAAA;gBAEvE,wDAAwD;gBACxD,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,6BAA6B,CACvE,QAAQ,CAAC,wBAAwB,EACjC,mBAAmB,EACnB,OAAO,CACR,CAAA;gBAED,oEAAoE;gBACpE,+FAA+F;gBAC/F,MAAM,gBAAgB,CAAC,iBAAiB,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAA;gBAEtE,IAAI,CAAC,IAAI,CACP,+BAA+B,IAAI,sBAAsB,YAAY,CAAC,UAAU,sBAAsB,YAAY,CAAC,WAAW,CAAC,MAAM,8BAA8B,CACpK,CAAA;gBAED,cAAc,CAAC,aAAa,GAAG,mBAAmB,CAAC,GAAG,CACpD,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAC9B,CAAA;gBACD,cAAc,CAAC,IAAI,GAAG,YAAY,CAAC,UAAU,CAAA;gBAC7C,cAAc,CAAC,WAAW,GAAG,YAAY,CAAC,WAAW,CAAA;aACtD;YACD,OAAO,cAAc,CAAA;QACvB,CAAC;KAAA;IAEK,gBAAgB,CACpB,IAAY,EACZ,IAAyB,EACzB,OAAqC;;YAErC,MAAM,kBAAkB,GAAG,IAAI,yCAAkB,EAAE,CAAA;YAEnD,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAA;YAC1D,IAAI,SAAS,CAAC,KAAK,KAAK,CAAC,EAAE;gBACzB,MAAM,IAAI,KAAK,CACb,0DAA0D,CAC3D,CAAA;aACF;YAED,MAAM,kBAAkB,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;gBACzD,OAAO,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAA;YAC/B,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,kBAAkB,EAAE;gBACvB,MAAM,IAAI,KAAK,CAAC,6CAA6C,IAAI,EAAE,CAAC,CAAA;aACrE;YAED,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,iBAAiB,CACtD,kBAAkB,CAAC,IAAI,EACvB,kBAAkB,CAAC,wBAAwB,CAC5C,CAAA;YAED,IAAI,CAAC,IAAI,EAAE;gBACT,IAAI,GAAG,wCAAqB,EAAE,CAAA;aAC/B;YACD,IAAI,GAAG,gBAAS,CAAC,IAAI,CAAC,CAAA;YACtB,IAAI,GAAG,cAAO,CAAC,IAAI,CAAC,CAAA;YAEpB,4IAA4I;YAC5I,MAAM,qBAAqB,GAAG,iDAAwB,CACpD,IAAI,EACJ,KAAK,CAAC,KAAK,EACX,IAAI,EACJ,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,oBAAoB,KAAI,KAAK,CACvC,CAAA;YAED,IAAI,qBAAqB,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE;gBACtD,IAAI,CAAC,IAAI,CACP,sDAAsD,kBAAkB,CAAC,IAAI,EAAE,CAChF,CAAA;aACF;iBAAM;gBACL,4EAA4E;gBAC5E,MAAM,oCAA4B,CAChC,qBAAqB,CAAC,kBAAkB,CACzC,CAAA;gBACD,IAAI,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAA;gBAChE,MAAM,mCAA2B,CAC/B,qBAAqB,CAAC,kBAAkB,CACzC,CAAA;gBACD,MAAM,kBAAkB,CAAC,sBAAsB,CAC7C,qBAAqB,CAAC,eAAe,CACtC,CAAA;aACF;YAED,OAAO;gBACL,YAAY,EAAE,IAAI;gBAClB,YAAY,EAAE,qBAAqB,CAAC,oBAAoB;aACzD,CAAA;QACH,CAAC;KAAA;IAEK,oBAAoB,CACxB,IAAyB;;YAEzB,MAAM,kBAAkB,GAAG,IAAI,yCAAkB,EAAE,CAAA;YAEnD,MAAM,QAAQ,GAAuB,EAAE,CAAA;YACvC,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,aAAa,EAAE,CAAA;YAC1D,IAAI,SAAS,CAAC,KAAK,KAAK,CAAC,EAAE;gBACzB,IAAI,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAA;gBACrE,OAAO,QAAQ,CAAA;aAChB;YAED,IAAI,CAAC,IAAI,EAAE;gBACT,IAAI,GAAG,wCAAqB,EAAE,CAAA;aAC/B;YACD,IAAI,GAAG,gBAAS,CAAC,IAAI,CAAC,CAAA;YACtB,IAAI,GAAG,cAAO,CAAC,IAAI,CAAC,CAAA;YAEpB,IAAI,mBAAmB,GAAG,CAAC,CAAA;YAC3B,OAAO,mBAAmB,GAAG,SAAS,CAAC,KAAK,EAAE;gBAC5C,MAAM,yBAAyB,GAAG,SAAS,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAA;gBACtE,mBAAmB,IAAI,CAAC,CAAA;gBAExB,kDAAkD;gBAClD,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,iBAAiB,CACtD,yBAAyB,CAAC,IAAI,EAC9B,yBAAyB,CAAC,wBAAwB,CACnD,CAAA;gBAED,MAAM,qBAAqB,GAAG,iDAAwB,CACpD,yBAAyB,CAAC,IAAI,EAC9B,KAAK,CAAC,KAAK,EACX,IAAI,EACJ,IAAI,CACL,CAAA;gBACD,IAAI,qBAAqB,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE;oBACtD,IAAI,CAAC,IAAI,CACP,qDAAqD,yBAAyB,CAAC,IAAI,EAAE,CACtF,CAAA;iBACF;qBAAM;oBACL,MAAM,oCAA4B,CAChC,qBAAqB,CAAC,kBAAkB,CACzC,CAAA;oBACD,MAAM,mCAA2B,CAC/B,qBAAqB,CAAC,kBAAkB,CACzC,CAAA;oBACD,MAAM,kBAAkB,CAAC,sBAAsB,CAC7C,qBAAqB,CAAC,eAAe,CACtC,CAAA;iBACF;gBAED,QAAQ,CAAC,IAAI,CAAC;oBACZ,YAAY,EAAE,yBAAyB,CAAC,IAAI;oBAC5C,YAAY,EAAE,qBAAqB,CAAC,oBAAoB;iBACzD,CAAC,CAAA;aACH;YACD,OAAO,QAAQ,CAAA;QACjB,CAAC;KAAA;CACF;AApMD,sDAoMC"}
|
||||
11
node_modules/@actions/artifact/lib/internal/config-variables.d.ts
generated
vendored
Normal file
11
node_modules/@actions/artifact/lib/internal/config-variables.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
export declare function getUploadFileConcurrency(): number;
|
||||
export declare function getUploadChunkSize(): number;
|
||||
export declare function getRetryLimit(): number;
|
||||
export declare function getRetryMultiplier(): number;
|
||||
export declare function getInitialRetryIntervalInMilliseconds(): number;
|
||||
export declare function getDownloadFileConcurrency(): number;
|
||||
export declare function getRuntimeToken(): string;
|
||||
export declare function getRuntimeUrl(): string;
|
||||
export declare function getWorkFlowRunId(): string;
|
||||
export declare function getWorkSpaceDirectory(): string;
|
||||
export declare function getRetentionDays(): string | undefined;
|
||||
71
node_modules/@actions/artifact/lib/internal/config-variables.js
generated
vendored
Normal file
71
node_modules/@actions/artifact/lib/internal/config-variables.js
generated
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// The number of concurrent uploads that happens at the same time
|
||||
function getUploadFileConcurrency() {
|
||||
return 2;
|
||||
}
|
||||
exports.getUploadFileConcurrency = getUploadFileConcurrency;
|
||||
// When uploading large files that can't be uploaded with a single http call, this controls
|
||||
// the chunk size that is used during upload
|
||||
function getUploadChunkSize() {
|
||||
return 8 * 1024 * 1024; // 8 MB Chunks
|
||||
}
|
||||
exports.getUploadChunkSize = getUploadChunkSize;
|
||||
// The maximum number of retries that can be attempted before an upload or download fails
|
||||
function getRetryLimit() {
|
||||
return 5;
|
||||
}
|
||||
exports.getRetryLimit = getRetryLimit;
|
||||
// With exponential backoff, the larger the retry count, the larger the wait time before another attempt
|
||||
// The retry multiplier controls by how much the backOff time increases depending on the number of retries
|
||||
function getRetryMultiplier() {
|
||||
return 1.5;
|
||||
}
|
||||
exports.getRetryMultiplier = getRetryMultiplier;
|
||||
// The initial wait time if an upload or download fails and a retry is being attempted for the first time
|
||||
function getInitialRetryIntervalInMilliseconds() {
|
||||
return 3000;
|
||||
}
|
||||
exports.getInitialRetryIntervalInMilliseconds = getInitialRetryIntervalInMilliseconds;
|
||||
// The number of concurrent downloads that happens at the same time
|
||||
function getDownloadFileConcurrency() {
|
||||
return 2;
|
||||
}
|
||||
exports.getDownloadFileConcurrency = getDownloadFileConcurrency;
|
||||
function getRuntimeToken() {
|
||||
const token = process.env['ACTIONS_RUNTIME_TOKEN'];
|
||||
if (!token) {
|
||||
throw new Error('Unable to get ACTIONS_RUNTIME_TOKEN env variable');
|
||||
}
|
||||
return token;
|
||||
}
|
||||
exports.getRuntimeToken = getRuntimeToken;
|
||||
function getRuntimeUrl() {
|
||||
const runtimeUrl = process.env['ACTIONS_RUNTIME_URL'];
|
||||
if (!runtimeUrl) {
|
||||
throw new Error('Unable to get ACTIONS_RUNTIME_URL env variable');
|
||||
}
|
||||
return runtimeUrl;
|
||||
}
|
||||
exports.getRuntimeUrl = getRuntimeUrl;
|
||||
function getWorkFlowRunId() {
|
||||
const workFlowRunId = process.env['GITHUB_RUN_ID'];
|
||||
if (!workFlowRunId) {
|
||||
throw new Error('Unable to get GITHUB_RUN_ID env variable');
|
||||
}
|
||||
return workFlowRunId;
|
||||
}
|
||||
exports.getWorkFlowRunId = getWorkFlowRunId;
|
||||
function getWorkSpaceDirectory() {
|
||||
const workspaceDirectory = process.env['GITHUB_WORKSPACE'];
|
||||
if (!workspaceDirectory) {
|
||||
throw new Error('Unable to get GITHUB_WORKSPACE env variable');
|
||||
}
|
||||
return workspaceDirectory;
|
||||
}
|
||||
exports.getWorkSpaceDirectory = getWorkSpaceDirectory;
|
||||
function getRetentionDays() {
|
||||
return process.env['GITHUB_RETENTION_DAYS'];
|
||||
}
|
||||
exports.getRetentionDays = getRetentionDays;
|
||||
//# sourceMappingURL=config-variables.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/config-variables.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/config-variables.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"config-variables.js","sourceRoot":"","sources":["../../src/internal/config-variables.ts"],"names":[],"mappings":";;AAAA,iEAAiE;AACjE,SAAgB,wBAAwB;IACtC,OAAO,CAAC,CAAA;AACV,CAAC;AAFD,4DAEC;AAED,2FAA2F;AAC3F,4CAA4C;AAC5C,SAAgB,kBAAkB;IAChC,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA,CAAC,cAAc;AACvC,CAAC;AAFD,gDAEC;AAED,yFAAyF;AACzF,SAAgB,aAAa;IAC3B,OAAO,CAAC,CAAA;AACV,CAAC;AAFD,sCAEC;AAED,wGAAwG;AACxG,0GAA0G;AAC1G,SAAgB,kBAAkB;IAChC,OAAO,GAAG,CAAA;AACZ,CAAC;AAFD,gDAEC;AAED,yGAAyG;AACzG,SAAgB,qCAAqC;IACnD,OAAO,IAAI,CAAA;AACb,CAAC;AAFD,sFAEC;AAED,mEAAmE;AACnE,SAAgB,0BAA0B;IACxC,OAAO,CAAC,CAAA;AACV,CAAC;AAFD,gEAEC;AAED,SAAgB,eAAe;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;IAClD,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;KACpE;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAND,0CAMC;AAED,SAAgB,aAAa;IAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;IACrD,IAAI,CAAC,UAAU,EAAE;QACf,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;KAClE;IACD,OAAO,UAAU,CAAA;AACnB,CAAC;AAND,sCAMC;AAED,SAAgB,gBAAgB;IAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAClD,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAA;KAC5D;IACD,OAAO,aAAa,CAAA;AACtB,CAAC;AAND,4CAMC;AAED,SAAgB,qBAAqB;IACnC,MAAM,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;IAC1D,IAAI,CAAC,kBAAkB,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;KAC/D;IACD,OAAO,kBAAkB,CAAA;AAC3B,CAAC;AAND,sDAMC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;AAC7C,CAAC;AAFD,4CAEC"}
|
||||
57
node_modules/@actions/artifact/lib/internal/contracts.d.ts
generated
vendored
Normal file
57
node_modules/@actions/artifact/lib/internal/contracts.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
export interface ArtifactResponse {
|
||||
containerId: string;
|
||||
size: number;
|
||||
signedContent: string;
|
||||
fileContainerResourceUrl: string;
|
||||
type: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
export interface CreateArtifactParameters {
|
||||
Type: string;
|
||||
Name: string;
|
||||
RetentionDays?: number;
|
||||
}
|
||||
export interface PatchArtifactSize {
|
||||
Size: number;
|
||||
}
|
||||
export interface PatchArtifactSizeSuccessResponse {
|
||||
containerId: number;
|
||||
size: number;
|
||||
signedContent: string;
|
||||
type: string;
|
||||
name: string;
|
||||
url: string;
|
||||
uploadUrl: string;
|
||||
}
|
||||
export interface UploadResults {
|
||||
uploadSize: number;
|
||||
totalSize: number;
|
||||
failedItems: string[];
|
||||
}
|
||||
export interface ListArtifactsResponse {
|
||||
count: number;
|
||||
value: ArtifactResponse[];
|
||||
}
|
||||
export interface QueryArtifactResponse {
|
||||
count: number;
|
||||
value: ContainerEntry[];
|
||||
}
|
||||
export interface ContainerEntry {
|
||||
containerId: number;
|
||||
scopeIdentifier: string;
|
||||
path: string;
|
||||
itemType: string;
|
||||
status: string;
|
||||
fileLength?: number;
|
||||
fileEncoding?: number;
|
||||
fileType?: number;
|
||||
dateCreated: string;
|
||||
dateLastModified: string;
|
||||
createdBy: string;
|
||||
lastModifiedBy: string;
|
||||
itemLocation: string;
|
||||
contentLocation: string;
|
||||
fileId?: number;
|
||||
contentId: string;
|
||||
}
|
||||
3
node_modules/@actions/artifact/lib/internal/contracts.js
generated
vendored
Normal file
3
node_modules/@actions/artifact/lib/internal/contracts.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=contracts.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/contracts.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/contracts.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/internal/contracts.ts"],"names":[],"mappings":""}
|
||||
39
node_modules/@actions/artifact/lib/internal/download-http-client.d.ts
generated
vendored
Normal file
39
node_modules/@actions/artifact/lib/internal/download-http-client.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/// <reference types="node" />
|
||||
import * as fs from 'fs';
|
||||
import { ListArtifactsResponse, QueryArtifactResponse } from './contracts';
|
||||
import { IHttpClientResponse } from '@actions/http-client/interfaces';
|
||||
import { DownloadItem } from './download-specification';
|
||||
export declare class DownloadHttpClient {
|
||||
private downloadHttpManager;
|
||||
private statusReporter;
|
||||
constructor();
|
||||
/**
|
||||
* Gets a list of all artifacts that are in a specific container
|
||||
*/
|
||||
listArtifacts(): Promise<ListArtifactsResponse>;
|
||||
/**
|
||||
* Fetches a set of container items that describe the contents of an artifact
|
||||
* @param artifactName the name of the artifact
|
||||
* @param containerUrl the artifact container URL for the run
|
||||
*/
|
||||
getContainerItems(artifactName: string, containerUrl: string): Promise<QueryArtifactResponse>;
|
||||
/**
|
||||
* Concurrently downloads all the files that are part of an artifact
|
||||
* @param downloadItems information about what items to download and where to save them
|
||||
*/
|
||||
downloadSingleArtifact(downloadItems: DownloadItem[]): Promise<void>;
|
||||
/**
|
||||
* Downloads an individual file
|
||||
* @param httpClientIndex the index of the http client that is used to make all of the calls
|
||||
* @param artifactLocation origin location where a file will be downloaded from
|
||||
* @param downloadPath destination location for the file being downloaded
|
||||
*/
|
||||
private downloadIndividualFile;
|
||||
/**
|
||||
* Pipes the response from downloading an individual file to the appropriate destination stream while decoding gzip content if necessary
|
||||
* @param response the http response received when downloading a file
|
||||
* @param destinationStream the stream where the file should be written to
|
||||
* @param isGzip a boolean denoting if the content is compressed using gzip and if we need to decode it
|
||||
*/
|
||||
pipeResponseToFile(response: IHttpClientResponse, destinationStream: fs.WriteStream, isGzip: boolean): Promise<void>;
|
||||
}
|
||||
275
node_modules/@actions/artifact/lib/internal/download-http-client.js
generated
vendored
Normal file
275
node_modules/@actions/artifact/lib/internal/download-http-client.js
generated
vendored
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
"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 = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = __importStar(require("fs"));
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const zlib = __importStar(require("zlib"));
|
||||
const utils_1 = require("./utils");
|
||||
const url_1 = require("url");
|
||||
const status_reporter_1 = require("./status-reporter");
|
||||
const perf_hooks_1 = require("perf_hooks");
|
||||
const http_manager_1 = require("./http-manager");
|
||||
const config_variables_1 = require("./config-variables");
|
||||
const requestUtils_1 = require("./requestUtils");
|
||||
class DownloadHttpClient {
|
||||
constructor() {
|
||||
this.downloadHttpManager = new http_manager_1.HttpManager(config_variables_1.getDownloadFileConcurrency(), '@actions/artifact-download');
|
||||
// downloads are usually significantly faster than uploads so display status information every second
|
||||
this.statusReporter = new status_reporter_1.StatusReporter(1000);
|
||||
}
|
||||
/**
|
||||
* Gets a list of all artifacts that are in a specific container
|
||||
*/
|
||||
listArtifacts() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const artifactUrl = utils_1.getArtifactUrl();
|
||||
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
||||
const client = this.downloadHttpManager.getClient(0);
|
||||
const headers = utils_1.getDownloadHeaders('application/json');
|
||||
const response = yield requestUtils_1.retryHttpClientRequest('List Artifacts', () => __awaiter(this, void 0, void 0, function* () { return client.get(artifactUrl, headers); }));
|
||||
const body = yield response.readBody();
|
||||
return JSON.parse(body);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Fetches a set of container items that describe the contents of an artifact
|
||||
* @param artifactName the name of the artifact
|
||||
* @param containerUrl the artifact container URL for the run
|
||||
*/
|
||||
getContainerItems(artifactName, containerUrl) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// the itemPath search parameter controls which containers will be returned
|
||||
const resourceUrl = new url_1.URL(containerUrl);
|
||||
resourceUrl.searchParams.append('itemPath', artifactName);
|
||||
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
||||
const client = this.downloadHttpManager.getClient(0);
|
||||
const headers = utils_1.getDownloadHeaders('application/json');
|
||||
const response = yield requestUtils_1.retryHttpClientRequest('Get Container Items', () => __awaiter(this, void 0, void 0, function* () { return client.get(resourceUrl.toString(), headers); }));
|
||||
const body = yield response.readBody();
|
||||
return JSON.parse(body);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Concurrently downloads all the files that are part of an artifact
|
||||
* @param downloadItems information about what items to download and where to save them
|
||||
*/
|
||||
downloadSingleArtifact(downloadItems) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const DOWNLOAD_CONCURRENCY = config_variables_1.getDownloadFileConcurrency();
|
||||
// limit the number of files downloaded at a single time
|
||||
core.debug(`Download file concurrency is set to ${DOWNLOAD_CONCURRENCY}`);
|
||||
const parallelDownloads = [...new Array(DOWNLOAD_CONCURRENCY).keys()];
|
||||
let currentFile = 0;
|
||||
let downloadedFiles = 0;
|
||||
core.info(`Total number of files that will be downloaded: ${downloadItems.length}`);
|
||||
this.statusReporter.setTotalNumberOfFilesToProcess(downloadItems.length);
|
||||
this.statusReporter.start();
|
||||
yield Promise.all(parallelDownloads.map((index) => __awaiter(this, void 0, void 0, function* () {
|
||||
while (currentFile < downloadItems.length) {
|
||||
const currentFileToDownload = downloadItems[currentFile];
|
||||
currentFile += 1;
|
||||
const startTime = perf_hooks_1.performance.now();
|
||||
yield this.downloadIndividualFile(index, currentFileToDownload.sourceLocation, currentFileToDownload.targetPath);
|
||||
if (core.isDebug()) {
|
||||
core.debug(`File: ${++downloadedFiles}/${downloadItems.length}. ${currentFileToDownload.targetPath} took ${(perf_hooks_1.performance.now() - startTime).toFixed(3)} milliseconds to finish downloading`);
|
||||
}
|
||||
this.statusReporter.incrementProcessedCount();
|
||||
}
|
||||
})))
|
||||
.catch(error => {
|
||||
throw new Error(`Unable to download the artifact: ${error}`);
|
||||
})
|
||||
.finally(() => {
|
||||
this.statusReporter.stop();
|
||||
// safety dispose all connections
|
||||
this.downloadHttpManager.disposeAndReplaceAllClients();
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Downloads an individual file
|
||||
* @param httpClientIndex the index of the http client that is used to make all of the calls
|
||||
* @param artifactLocation origin location where a file will be downloaded from
|
||||
* @param downloadPath destination location for the file being downloaded
|
||||
*/
|
||||
downloadIndividualFile(httpClientIndex, artifactLocation, downloadPath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let retryCount = 0;
|
||||
const retryLimit = config_variables_1.getRetryLimit();
|
||||
let destinationStream = fs.createWriteStream(downloadPath);
|
||||
const headers = utils_1.getDownloadHeaders('application/json', true, true);
|
||||
// a single GET request is used to download a file
|
||||
const makeDownloadRequest = () => __awaiter(this, void 0, void 0, function* () {
|
||||
const client = this.downloadHttpManager.getClient(httpClientIndex);
|
||||
return yield client.get(artifactLocation, headers);
|
||||
});
|
||||
// check the response headers to determine if the file was compressed using gzip
|
||||
const isGzip = (incomingHeaders) => {
|
||||
return ('content-encoding' in incomingHeaders &&
|
||||
incomingHeaders['content-encoding'] === 'gzip');
|
||||
};
|
||||
// Increments the current retry count and then checks if the retry limit has been reached
|
||||
// If there have been too many retries, fail so the download stops. If there is a retryAfterValue value provided,
|
||||
// it will be used
|
||||
const backOff = (retryAfterValue) => __awaiter(this, void 0, void 0, function* () {
|
||||
retryCount++;
|
||||
if (retryCount > retryLimit) {
|
||||
return Promise.reject(new Error(`Retry limit has been reached. Unable to download ${artifactLocation}`));
|
||||
}
|
||||
else {
|
||||
this.downloadHttpManager.disposeAndReplaceClient(httpClientIndex);
|
||||
if (retryAfterValue) {
|
||||
// Back off by waiting the specified time denoted by the retry-after header
|
||||
core.info(`Backoff due to too many requests, retry #${retryCount}. Waiting for ${retryAfterValue} milliseconds before continuing the download`);
|
||||
yield utils_1.sleep(retryAfterValue);
|
||||
}
|
||||
else {
|
||||
// Back off using an exponential value that depends on the retry count
|
||||
const backoffTime = utils_1.getExponentialRetryTimeInMilliseconds(retryCount);
|
||||
core.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the download`);
|
||||
yield utils_1.sleep(backoffTime);
|
||||
}
|
||||
core.info(`Finished backoff for retry #${retryCount}, continuing with download`);
|
||||
}
|
||||
});
|
||||
const isAllBytesReceived = (expected, received) => {
|
||||
// be lenient, if any input is missing, assume success, i.e. not truncated
|
||||
if (!expected ||
|
||||
!received ||
|
||||
process.env['ACTIONS_ARTIFACT_SKIP_DOWNLOAD_VALIDATION']) {
|
||||
core.info('Skipping download validation.');
|
||||
return true;
|
||||
}
|
||||
return parseInt(expected) === received;
|
||||
};
|
||||
const resetDestinationStream = (fileDownloadPath) => __awaiter(this, void 0, void 0, function* () {
|
||||
destinationStream.close();
|
||||
yield utils_1.rmFile(fileDownloadPath);
|
||||
destinationStream = fs.createWriteStream(fileDownloadPath);
|
||||
});
|
||||
// keep trying to download a file until a retry limit has been reached
|
||||
while (retryCount <= retryLimit) {
|
||||
let response;
|
||||
try {
|
||||
response = yield makeDownloadRequest();
|
||||
if (core.isDebug()) {
|
||||
utils_1.displayHttpDiagnostics(response);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
// if an error is caught, it is usually indicative of a timeout so retry the download
|
||||
core.info('An error occurred while attempting to download a file');
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
// increment the retryCount and use exponential backoff to wait before making the next request
|
||||
yield backOff();
|
||||
continue;
|
||||
}
|
||||
let forceRetry = false;
|
||||
if (utils_1.isSuccessStatusCode(response.message.statusCode)) {
|
||||
// The body contains the contents of the file however calling response.readBody() causes all the content to be converted to a string
|
||||
// which can cause some gzip encoded data to be lost
|
||||
// Instead of using response.readBody(), response.message is a readableStream that can be directly used to get the raw body contents
|
||||
try {
|
||||
const isGzipped = isGzip(response.message.headers);
|
||||
yield this.pipeResponseToFile(response, destinationStream, isGzipped);
|
||||
if (isGzipped ||
|
||||
isAllBytesReceived(response.message.headers['content-length'], yield utils_1.getFileSize(downloadPath))) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
forceRetry = true;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
// retry on error, most likely streams were corrupted
|
||||
forceRetry = true;
|
||||
}
|
||||
}
|
||||
if (forceRetry || utils_1.isRetryableStatusCode(response.message.statusCode)) {
|
||||
core.info(`A ${response.message.statusCode} response code has been received while attempting to download an artifact`);
|
||||
resetDestinationStream(downloadPath);
|
||||
// if a throttled status code is received, try to get the retryAfter header value, else differ to standard exponential backoff
|
||||
utils_1.isThrottledStatusCode(response.message.statusCode)
|
||||
? yield backOff(utils_1.tryGetRetryAfterValueTimeInMilliseconds(response.message.headers))
|
||||
: yield backOff();
|
||||
}
|
||||
else {
|
||||
// Some unexpected response code, fail immediately and stop the download
|
||||
utils_1.displayHttpDiagnostics(response);
|
||||
return Promise.reject(new Error(`Unexpected http ${response.message.statusCode} during download for ${artifactLocation}`));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Pipes the response from downloading an individual file to the appropriate destination stream while decoding gzip content if necessary
|
||||
* @param response the http response received when downloading a file
|
||||
* @param destinationStream the stream where the file should be written to
|
||||
* @param isGzip a boolean denoting if the content is compressed using gzip and if we need to decode it
|
||||
*/
|
||||
pipeResponseToFile(response, destinationStream, isGzip) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield new Promise((resolve, reject) => {
|
||||
if (isGzip) {
|
||||
const gunzip = zlib.createGunzip();
|
||||
response.message
|
||||
.on('error', error => {
|
||||
core.error(`An error occurred while attempting to read the response stream`);
|
||||
gunzip.close();
|
||||
destinationStream.close();
|
||||
reject(error);
|
||||
})
|
||||
.pipe(gunzip)
|
||||
.on('error', error => {
|
||||
core.error(`An error occurred while attempting to decompress the response stream`);
|
||||
destinationStream.close();
|
||||
reject(error);
|
||||
})
|
||||
.pipe(destinationStream)
|
||||
.on('close', () => {
|
||||
resolve();
|
||||
})
|
||||
.on('error', error => {
|
||||
core.error(`An error occurred while writing a downloaded file to ${destinationStream.path}`);
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response.message
|
||||
.on('error', error => {
|
||||
core.error(`An error occurred while attempting to read the response stream`);
|
||||
destinationStream.close();
|
||||
reject(error);
|
||||
})
|
||||
.pipe(destinationStream)
|
||||
.on('close', () => {
|
||||
resolve();
|
||||
})
|
||||
.on('error', error => {
|
||||
core.error(`An error occurred while writing a downloaded file to ${destinationStream.path}`);
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.DownloadHttpClient = DownloadHttpClient;
|
||||
//# sourceMappingURL=download-http-client.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/download-http-client.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/download-http-client.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
7
node_modules/@actions/artifact/lib/internal/download-options.d.ts
generated
vendored
Normal file
7
node_modules/@actions/artifact/lib/internal/download-options.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export interface DownloadOptions {
|
||||
/**
|
||||
* Specifies if a folder is created for the artifact that is downloaded (contents downloaded into this folder),
|
||||
* defaults to false if not specified
|
||||
* */
|
||||
createArtifactFolder?: boolean;
|
||||
}
|
||||
3
node_modules/@actions/artifact/lib/internal/download-options.js
generated
vendored
Normal file
3
node_modules/@actions/artifact/lib/internal/download-options.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=download-options.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/download-options.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/download-options.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"download-options.js","sourceRoot":"","sources":["../../src/internal/download-options.ts"],"names":[],"mappings":""}
|
||||
10
node_modules/@actions/artifact/lib/internal/download-response.d.ts
generated
vendored
Normal file
10
node_modules/@actions/artifact/lib/internal/download-response.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export interface DownloadResponse {
|
||||
/**
|
||||
* The name of the artifact that was downloaded
|
||||
*/
|
||||
artifactName: string;
|
||||
/**
|
||||
* The full Path to where the artifact was downloaded
|
||||
*/
|
||||
downloadPath: string;
|
||||
}
|
||||
3
node_modules/@actions/artifact/lib/internal/download-response.js
generated
vendored
Normal file
3
node_modules/@actions/artifact/lib/internal/download-response.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=download-response.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/download-response.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/download-response.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"download-response.js","sourceRoot":"","sources":["../../src/internal/download-response.ts"],"names":[],"mappings":""}
|
||||
19
node_modules/@actions/artifact/lib/internal/download-specification.d.ts
generated
vendored
Normal file
19
node_modules/@actions/artifact/lib/internal/download-specification.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import { ContainerEntry } from './contracts';
|
||||
export interface DownloadSpecification {
|
||||
rootDownloadLocation: string;
|
||||
directoryStructure: string[];
|
||||
emptyFilesToCreate: string[];
|
||||
filesToDownload: DownloadItem[];
|
||||
}
|
||||
export interface DownloadItem {
|
||||
sourceLocation: string;
|
||||
targetPath: string;
|
||||
}
|
||||
/**
|
||||
* Creates a specification for a set of files that will be downloaded
|
||||
* @param artifactName the name of the artifact
|
||||
* @param artifactEntries a set of container entries that describe that files that make up an artifact
|
||||
* @param downloadPath the path where the artifact will be downloaded to
|
||||
* @param includeRootDirectory specifies if there should be an extra directory (denoted by the artifact name) where the artifact files should be downloaded to
|
||||
*/
|
||||
export declare function getDownloadSpecification(artifactName: string, artifactEntries: ContainerEntry[], downloadPath: string, includeRootDirectory: boolean): DownloadSpecification;
|
||||
61
node_modules/@actions/artifact/lib/internal/download-specification.js
generated
vendored
Normal file
61
node_modules/@actions/artifact/lib/internal/download-specification.js
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
"use strict";
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const path = __importStar(require("path"));
|
||||
/**
|
||||
* Creates a specification for a set of files that will be downloaded
|
||||
* @param artifactName the name of the artifact
|
||||
* @param artifactEntries a set of container entries that describe that files that make up an artifact
|
||||
* @param downloadPath the path where the artifact will be downloaded to
|
||||
* @param includeRootDirectory specifies if there should be an extra directory (denoted by the artifact name) where the artifact files should be downloaded to
|
||||
*/
|
||||
function getDownloadSpecification(artifactName, artifactEntries, downloadPath, includeRootDirectory) {
|
||||
// use a set for the directory paths so that there are no duplicates
|
||||
const directories = new Set();
|
||||
const specifications = {
|
||||
rootDownloadLocation: includeRootDirectory
|
||||
? path.join(downloadPath, artifactName)
|
||||
: downloadPath,
|
||||
directoryStructure: [],
|
||||
emptyFilesToCreate: [],
|
||||
filesToDownload: []
|
||||
};
|
||||
for (const entry of artifactEntries) {
|
||||
// Ignore artifacts in the container that don't begin with the same name
|
||||
if (entry.path.startsWith(`${artifactName}/`) ||
|
||||
entry.path.startsWith(`${artifactName}\\`)) {
|
||||
// normalize all separators to the local OS
|
||||
const normalizedPathEntry = path.normalize(entry.path);
|
||||
// entry.path always starts with the artifact name, if includeRootDirectory is false, remove the name from the beginning of the path
|
||||
const filePath = path.join(downloadPath, includeRootDirectory
|
||||
? normalizedPathEntry
|
||||
: normalizedPathEntry.replace(artifactName, ''));
|
||||
// Case insensitive folder structure maintained in the backend, not every folder is created so the 'folder'
|
||||
// itemType cannot be relied upon. The file must be used to determine the directory structure
|
||||
if (entry.itemType === 'file') {
|
||||
// Get the directories that we need to create from the filePath for each individual file
|
||||
directories.add(path.dirname(filePath));
|
||||
if (entry.fileLength === 0) {
|
||||
// An empty file was uploaded, create the empty files locally so that no extra http calls are made
|
||||
specifications.emptyFilesToCreate.push(filePath);
|
||||
}
|
||||
else {
|
||||
specifications.filesToDownload.push({
|
||||
sourceLocation: entry.contentLocation,
|
||||
targetPath: filePath
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
specifications.directoryStructure = Array.from(directories);
|
||||
return specifications;
|
||||
}
|
||||
exports.getDownloadSpecification = getDownloadSpecification;
|
||||
//# sourceMappingURL=download-specification.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/download-specification.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/download-specification.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"download-specification.js","sourceRoot":"","sources":["../../src/internal/download-specification.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4B;AAyB5B;;;;;;GAMG;AACH,SAAgB,wBAAwB,CACtC,YAAoB,EACpB,eAAiC,EACjC,YAAoB,EACpB,oBAA6B;IAE7B,oEAAoE;IACpE,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAErC,MAAM,cAAc,GAA0B;QAC5C,oBAAoB,EAAE,oBAAoB;YACxC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC;YACvC,CAAC,CAAC,YAAY;QAChB,kBAAkB,EAAE,EAAE;QACtB,kBAAkB,EAAE,EAAE;QACtB,eAAe,EAAE,EAAE;KACpB,CAAA;IAED,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE;QACnC,wEAAwE;QACxE,IACE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,YAAY,GAAG,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,YAAY,IAAI,CAAC,EAC1C;YACA,2CAA2C;YAC3C,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACtD,oIAAoI;YACpI,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CACxB,YAAY,EACZ,oBAAoB;gBAClB,CAAC,CAAC,mBAAmB;gBACrB,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAClD,CAAA;YAED,2GAA2G;YAC3G,6FAA6F;YAC7F,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE;gBAC7B,wFAAwF;gBACxF,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAA;gBACvC,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC,EAAE;oBAC1B,kGAAkG;oBAClG,cAAc,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;iBACjD;qBAAM;oBACL,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC;wBAClC,cAAc,EAAE,KAAK,CAAC,eAAe;wBACrC,UAAU,EAAE,QAAQ;qBACrB,CAAC,CAAA;iBACH;aACF;SACF;KACF;IAED,cAAc,CAAC,kBAAkB,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IAC3D,OAAO,cAAc,CAAA;AACvB,CAAC;AAtDD,4DAsDC"}
|
||||
12
node_modules/@actions/artifact/lib/internal/http-manager.d.ts
generated
vendored
Normal file
12
node_modules/@actions/artifact/lib/internal/http-manager.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { HttpClient } from '@actions/http-client/index';
|
||||
/**
|
||||
* Used for managing http clients during either upload or download
|
||||
*/
|
||||
export declare class HttpManager {
|
||||
private clients;
|
||||
private userAgent;
|
||||
constructor(clientCount: number, userAgent: string);
|
||||
getClient(index: number): HttpClient;
|
||||
disposeAndReplaceClient(index: number): void;
|
||||
disposeAndReplaceAllClients(): void;
|
||||
}
|
||||
31
node_modules/@actions/artifact/lib/internal/http-manager.js
generated
vendored
Normal file
31
node_modules/@actions/artifact/lib/internal/http-manager.js
generated
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* Used for managing http clients during either upload or download
|
||||
*/
|
||||
class HttpManager {
|
||||
constructor(clientCount, userAgent) {
|
||||
if (clientCount < 1) {
|
||||
throw new Error('There must be at least one client');
|
||||
}
|
||||
this.userAgent = userAgent;
|
||||
this.clients = new Array(clientCount).fill(utils_1.createHttpClient(userAgent));
|
||||
}
|
||||
getClient(index) {
|
||||
return this.clients[index];
|
||||
}
|
||||
// client disposal is necessary if a keep-alive connection is used to properly close the connection
|
||||
// for more information see: https://github.com/actions/http-client/blob/04e5ad73cd3fd1f5610a32116b0759eddf6570d2/index.ts#L292
|
||||
disposeAndReplaceClient(index) {
|
||||
this.clients[index].dispose();
|
||||
this.clients[index] = utils_1.createHttpClient(this.userAgent);
|
||||
}
|
||||
disposeAndReplaceAllClients() {
|
||||
for (const [index] of this.clients.entries()) {
|
||||
this.disposeAndReplaceClient(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.HttpManager = HttpManager;
|
||||
//# sourceMappingURL=http-manager.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/http-manager.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/http-manager.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"http-manager.js","sourceRoot":"","sources":["../../src/internal/http-manager.ts"],"names":[],"mappings":";;AACA,mCAAwC;AAExC;;GAEG;AACH,MAAa,WAAW;IAItB,YAAY,WAAmB,EAAE,SAAiB;QAChD,IAAI,WAAW,GAAG,CAAC,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;SACrD;QACD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,wBAAgB,CAAC,SAAS,CAAC,CAAC,CAAA;IACzE,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC5B,CAAC;IAED,mGAAmG;IACnG,+HAA+H;IAC/H,uBAAuB,CAAC,KAAa;QACnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,wBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACxD,CAAC;IAED,2BAA2B;QACzB,KAAK,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE;YAC5C,IAAI,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAA;SACpC;IACH,CAAC;CACF;AA5BD,kCA4BC"}
|
||||
3
node_modules/@actions/artifact/lib/internal/requestUtils.d.ts
generated
vendored
Normal file
3
node_modules/@actions/artifact/lib/internal/requestUtils.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { IHttpClientResponse } from '@actions/http-client/interfaces';
|
||||
export declare function retry(name: string, operation: () => Promise<IHttpClientResponse>, customErrorMessages: Map<number, string>, maxAttempts: number): Promise<IHttpClientResponse>;
|
||||
export declare function retryHttpClientRequest<T>(name: string, method: () => Promise<IHttpClientResponse>, customErrorMessages?: Map<number, string>, maxAttempts?: number): Promise<IHttpClientResponse>;
|
||||
75
node_modules/@actions/artifact/lib/internal/requestUtils.js
generated
vendored
Normal file
75
node_modules/@actions/artifact/lib/internal/requestUtils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
"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 = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const utils_1 = require("./utils");
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const config_variables_1 = require("./config-variables");
|
||||
function retry(name, operation, customErrorMessages, maxAttempts) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let response = undefined;
|
||||
let statusCode = undefined;
|
||||
let isRetryable = false;
|
||||
let errorMessage = '';
|
||||
let customErrorInformation = undefined;
|
||||
let attempt = 1;
|
||||
while (attempt <= maxAttempts) {
|
||||
try {
|
||||
response = yield operation();
|
||||
statusCode = response.message.statusCode;
|
||||
if (utils_1.isSuccessStatusCode(statusCode)) {
|
||||
return response;
|
||||
}
|
||||
// Extra error information that we want to display if a particular response code is hit
|
||||
if (statusCode) {
|
||||
customErrorInformation = customErrorMessages.get(statusCode);
|
||||
}
|
||||
isRetryable = utils_1.isRetryableStatusCode(statusCode);
|
||||
errorMessage = `Artifact service responded with ${statusCode}`;
|
||||
}
|
||||
catch (error) {
|
||||
isRetryable = true;
|
||||
errorMessage = error.message;
|
||||
}
|
||||
if (!isRetryable) {
|
||||
core.info(`${name} - Error is not retryable`);
|
||||
if (response) {
|
||||
utils_1.displayHttpDiagnostics(response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
core.info(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`);
|
||||
yield utils_1.sleep(utils_1.getExponentialRetryTimeInMilliseconds(attempt));
|
||||
attempt++;
|
||||
}
|
||||
if (response) {
|
||||
utils_1.displayHttpDiagnostics(response);
|
||||
}
|
||||
if (customErrorInformation) {
|
||||
throw Error(`${name} failed: ${customErrorInformation}`);
|
||||
}
|
||||
throw Error(`${name} failed: ${errorMessage}`);
|
||||
});
|
||||
}
|
||||
exports.retry = retry;
|
||||
function retryHttpClientRequest(name, method, customErrorMessages = new Map(), maxAttempts = config_variables_1.getRetryLimit()) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return yield retry(name, method, customErrorMessages, maxAttempts);
|
||||
});
|
||||
}
|
||||
exports.retryHttpClientRequest = retryHttpClientRequest;
|
||||
//# sourceMappingURL=requestUtils.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/requestUtils.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/requestUtils.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"requestUtils.js","sourceRoot":"","sources":["../../src/internal/requestUtils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AACA,mCAMgB;AAChB,oDAAqC;AACrC,yDAAgD;AAEhD,SAAsB,KAAK,CACzB,IAAY,EACZ,SAA6C,EAC7C,mBAAwC,EACxC,WAAmB;;QAEnB,IAAI,QAAQ,GAAoC,SAAS,CAAA;QACzD,IAAI,UAAU,GAAuB,SAAS,CAAA;QAC9C,IAAI,WAAW,GAAG,KAAK,CAAA;QACvB,IAAI,YAAY,GAAG,EAAE,CAAA;QACrB,IAAI,sBAAsB,GAAuB,SAAS,CAAA;QAC1D,IAAI,OAAO,GAAG,CAAC,CAAA;QAEf,OAAO,OAAO,IAAI,WAAW,EAAE;YAC7B,IAAI;gBACF,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAA;gBAC5B,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAA;gBAExC,IAAI,2BAAmB,CAAC,UAAU,CAAC,EAAE;oBACnC,OAAO,QAAQ,CAAA;iBAChB;gBAED,uFAAuF;gBACvF,IAAI,UAAU,EAAE;oBACd,sBAAsB,GAAG,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;iBAC7D;gBAED,WAAW,GAAG,6BAAqB,CAAC,UAAU,CAAC,CAAA;gBAC/C,YAAY,GAAG,mCAAmC,UAAU,EAAE,CAAA;aAC/D;YAAC,OAAO,KAAK,EAAE;gBACd,WAAW,GAAG,IAAI,CAAA;gBAClB,YAAY,GAAG,KAAK,CAAC,OAAO,CAAA;aAC7B;YAED,IAAI,CAAC,WAAW,EAAE;gBAChB,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,2BAA2B,CAAC,CAAA;gBAC7C,IAAI,QAAQ,EAAE;oBACZ,8BAAsB,CAAC,QAAQ,CAAC,CAAA;iBACjC;gBACD,MAAK;aACN;YAED,IAAI,CAAC,IAAI,CACP,GAAG,IAAI,cAAc,OAAO,OAAO,WAAW,uBAAuB,YAAY,EAAE,CACpF,CAAA;YAED,MAAM,aAAK,CAAC,6CAAqC,CAAC,OAAO,CAAC,CAAC,CAAA;YAC3D,OAAO,EAAE,CAAA;SACV;QAED,IAAI,QAAQ,EAAE;YACZ,8BAAsB,CAAC,QAAQ,CAAC,CAAA;SACjC;QAED,IAAI,sBAAsB,EAAE;YAC1B,MAAM,KAAK,CAAC,GAAG,IAAI,YAAY,sBAAsB,EAAE,CAAC,CAAA;SACzD;QACD,MAAM,KAAK,CAAC,GAAG,IAAI,YAAY,YAAY,EAAE,CAAC,CAAA;IAChD,CAAC;CAAA;AA1DD,sBA0DC;AAED,SAAsB,sBAAsB,CAC1C,IAAY,EACZ,MAA0C,EAC1C,sBAA2C,IAAI,GAAG,EAAE,EACpD,WAAW,GAAG,gCAAa,EAAE;;QAE7B,OAAO,MAAM,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,mBAAmB,EAAE,WAAW,CAAC,CAAA;IACpE,CAAC;CAAA;AAPD,wDAOC"}
|
||||
22
node_modules/@actions/artifact/lib/internal/status-reporter.d.ts
generated
vendored
Normal file
22
node_modules/@actions/artifact/lib/internal/status-reporter.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Status Reporter that displays information about the progress/status of an artifact that is being uploaded or downloaded
|
||||
*
|
||||
* Variable display time that can be adjusted using the displayFrequencyInMilliseconds variable
|
||||
* The total status of the upload/download gets displayed according to this value
|
||||
* If there is a large file that is being uploaded, extra information about the individual status can also be displayed using the updateLargeFileStatus function
|
||||
*/
|
||||
export declare class StatusReporter {
|
||||
private totalNumberOfFilesToProcess;
|
||||
private processedCount;
|
||||
private displayFrequencyInMilliseconds;
|
||||
private largeFiles;
|
||||
private totalFileStatus;
|
||||
private largeFileStatus;
|
||||
constructor(displayFrequencyInMilliseconds: number);
|
||||
setTotalNumberOfFilesToProcess(fileTotal: number): void;
|
||||
start(): void;
|
||||
updateLargeFileStatus(fileName: string, numerator: number, denominator: number): void;
|
||||
stop(): void;
|
||||
incrementProcessedCount(): void;
|
||||
private formatPercentage;
|
||||
}
|
||||
64
node_modules/@actions/artifact/lib/internal/status-reporter.js
generated
vendored
Normal file
64
node_modules/@actions/artifact/lib/internal/status-reporter.js
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core_1 = require("@actions/core");
|
||||
/**
|
||||
* Status Reporter that displays information about the progress/status of an artifact that is being uploaded or downloaded
|
||||
*
|
||||
* Variable display time that can be adjusted using the displayFrequencyInMilliseconds variable
|
||||
* The total status of the upload/download gets displayed according to this value
|
||||
* If there is a large file that is being uploaded, extra information about the individual status can also be displayed using the updateLargeFileStatus function
|
||||
*/
|
||||
class StatusReporter {
|
||||
constructor(displayFrequencyInMilliseconds) {
|
||||
this.totalNumberOfFilesToProcess = 0;
|
||||
this.processedCount = 0;
|
||||
this.largeFiles = new Map();
|
||||
this.totalFileStatus = undefined;
|
||||
this.largeFileStatus = undefined;
|
||||
this.displayFrequencyInMilliseconds = displayFrequencyInMilliseconds;
|
||||
}
|
||||
setTotalNumberOfFilesToProcess(fileTotal) {
|
||||
this.totalNumberOfFilesToProcess = fileTotal;
|
||||
}
|
||||
start() {
|
||||
// displays information about the total upload/download status
|
||||
this.totalFileStatus = setInterval(() => {
|
||||
// display 1 decimal place without any rounding
|
||||
const percentage = this.formatPercentage(this.processedCount, this.totalNumberOfFilesToProcess);
|
||||
core_1.info(`Total file count: ${this.totalNumberOfFilesToProcess} ---- Processed file #${this.processedCount} (${percentage.slice(0, percentage.indexOf('.') + 2)}%)`);
|
||||
}, this.displayFrequencyInMilliseconds);
|
||||
// displays extra information about any large files that take a significant amount of time to upload or download every 1 second
|
||||
this.largeFileStatus = setInterval(() => {
|
||||
for (const value of Array.from(this.largeFiles.values())) {
|
||||
core_1.info(value);
|
||||
}
|
||||
// delete all entries in the map after displaying the information so it will not be displayed again unless explicitly added
|
||||
this.largeFiles.clear();
|
||||
}, 1000);
|
||||
}
|
||||
// if there is a large file that is being uploaded in chunks, this is used to display extra information about the status of the upload
|
||||
updateLargeFileStatus(fileName, numerator, denominator) {
|
||||
// display 1 decimal place without any rounding
|
||||
const percentage = this.formatPercentage(numerator, denominator);
|
||||
const displayInformation = `Uploading ${fileName} (${percentage.slice(0, percentage.indexOf('.') + 2)}%)`;
|
||||
// any previously added display information should be overwritten for the specific large file because a map is being used
|
||||
this.largeFiles.set(fileName, displayInformation);
|
||||
}
|
||||
stop() {
|
||||
if (this.totalFileStatus) {
|
||||
clearInterval(this.totalFileStatus);
|
||||
}
|
||||
if (this.largeFileStatus) {
|
||||
clearInterval(this.largeFileStatus);
|
||||
}
|
||||
}
|
||||
incrementProcessedCount() {
|
||||
this.processedCount++;
|
||||
}
|
||||
formatPercentage(numerator, denominator) {
|
||||
// toFixed() rounds, so use extra precision to display accurate information even though 4 decimal places are not displayed
|
||||
return ((numerator / denominator) * 100).toFixed(4).toString();
|
||||
}
|
||||
}
|
||||
exports.StatusReporter = StatusReporter;
|
||||
//# sourceMappingURL=status-reporter.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/status-reporter.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/status-reporter.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"status-reporter.js","sourceRoot":"","sources":["../../src/internal/status-reporter.ts"],"names":[],"mappings":";;AAAA,wCAAkC;AAElC;;;;;;GAMG;AAEH,MAAa,cAAc;IAQzB,YAAY,8BAAsC;QAP1C,gCAA2B,GAAG,CAAC,CAAA;QAC/B,mBAAc,GAAG,CAAC,CAAA;QAElB,eAAU,GAAG,IAAI,GAAG,EAAkB,CAAA;QAK5C,IAAI,CAAC,eAAe,GAAG,SAAS,CAAA;QAChC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAA;QAChC,IAAI,CAAC,8BAA8B,GAAG,8BAA8B,CAAA;IACtE,CAAC;IAED,8BAA8B,CAAC,SAAiB;QAC9C,IAAI,CAAC,2BAA2B,GAAG,SAAS,CAAA;IAC9C,CAAC;IAED,KAAK;QACH,8DAA8D;QAC9D,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,+CAA+C;YAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CACtC,IAAI,CAAC,cAAc,EACnB,IAAI,CAAC,2BAA2B,CACjC,CAAA;YACD,WAAI,CACF,qBACE,IAAI,CAAC,2BACP,yBAAyB,IAAI,CAAC,cAAc,KAAK,UAAU,CAAC,KAAK,CAC/D,CAAC,EACD,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAC5B,IAAI,CACN,CAAA;QACH,CAAC,EAAE,IAAI,CAAC,8BAA8B,CAAC,CAAA;QAEvC,+HAA+H;QAC/H,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE;gBACxD,WAAI,CAAC,KAAK,CAAC,CAAA;aACZ;YACD,2HAA2H;YAC3H,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;QACzB,CAAC,EAAE,IAAI,CAAC,CAAA;IACV,CAAC;IAED,sIAAsI;IACtI,qBAAqB,CACnB,QAAgB,EAChB,SAAiB,EACjB,WAAmB;QAEnB,+CAA+C;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;QAChE,MAAM,kBAAkB,GAAG,aAAa,QAAQ,KAAK,UAAU,CAAC,KAAK,CACnE,CAAC,EACD,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAC5B,IAAI,CAAA;QAEL,yHAAyH;QACzH,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAA;IACnD,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;SACpC;QAED,IAAI,IAAI,CAAC,eAAe,EAAE;YACxB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;SACpC;IACH,CAAC;IAED,uBAAuB;QACrB,IAAI,CAAC,cAAc,EAAE,CAAA;IACvB,CAAC;IAEO,gBAAgB,CAAC,SAAiB,EAAE,WAAmB;QAC7D,0HAA0H;QAC1H,OAAO,CAAC,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IAChE,CAAC;CACF;AAjFD,wCAiFC"}
|
||||
14
node_modules/@actions/artifact/lib/internal/upload-gzip.d.ts
generated
vendored
Normal file
14
node_modules/@actions/artifact/lib/internal/upload-gzip.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/// <reference types="node" />
|
||||
/**
|
||||
* Creates a Gzip compressed file of an original file at the provided temporary filepath location
|
||||
* @param {string} originalFilePath filepath of whatever will be compressed. The original file will be unmodified
|
||||
* @param {string} tempFilePath the location of where the Gzip file will be created
|
||||
* @returns the size of gzip file that gets created
|
||||
*/
|
||||
export declare function createGZipFileOnDisk(originalFilePath: string, tempFilePath: string): Promise<number>;
|
||||
/**
|
||||
* Creates a GZip file in memory using a buffer. Should be used for smaller files to reduce disk I/O
|
||||
* @param originalFilePath the path to the original file that is being GZipped
|
||||
* @returns a buffer with the GZip file
|
||||
*/
|
||||
export declare function createGZipFileInBuffer(originalFilePath: string): Promise<Buffer>;
|
||||
89
node_modules/@actions/artifact/lib/internal/upload-gzip.js
generated
vendored
Normal file
89
node_modules/@actions/artifact/lib/internal/upload-gzip.js
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
"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 __asyncValues = (this && this.__asyncValues) || function (o) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var m = o[Symbol.asyncIterator], i;
|
||||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
||||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
||||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = __importStar(require("fs"));
|
||||
const zlib = __importStar(require("zlib"));
|
||||
const util_1 = require("util");
|
||||
const stat = util_1.promisify(fs.stat);
|
||||
/**
|
||||
* Creates a Gzip compressed file of an original file at the provided temporary filepath location
|
||||
* @param {string} originalFilePath filepath of whatever will be compressed. The original file will be unmodified
|
||||
* @param {string} tempFilePath the location of where the Gzip file will be created
|
||||
* @returns the size of gzip file that gets created
|
||||
*/
|
||||
function createGZipFileOnDisk(originalFilePath, tempFilePath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const inputStream = fs.createReadStream(originalFilePath);
|
||||
const gzip = zlib.createGzip();
|
||||
const outputStream = fs.createWriteStream(tempFilePath);
|
||||
inputStream.pipe(gzip).pipe(outputStream);
|
||||
outputStream.on('finish', () => __awaiter(this, void 0, void 0, function* () {
|
||||
// wait for stream to finish before calculating the size which is needed as part of the Content-Length header when starting an upload
|
||||
const size = (yield stat(tempFilePath)).size;
|
||||
resolve(size);
|
||||
}));
|
||||
outputStream.on('error', error => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
reject;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.createGZipFileOnDisk = createGZipFileOnDisk;
|
||||
/**
|
||||
* Creates a GZip file in memory using a buffer. Should be used for smaller files to reduce disk I/O
|
||||
* @param originalFilePath the path to the original file that is being GZipped
|
||||
* @returns a buffer with the GZip file
|
||||
*/
|
||||
function createGZipFileInBuffer(originalFilePath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
|
||||
var e_1, _a;
|
||||
const inputStream = fs.createReadStream(originalFilePath);
|
||||
const gzip = zlib.createGzip();
|
||||
inputStream.pipe(gzip);
|
||||
// read stream into buffer, using experimental async iterators see https://github.com/nodejs/readable-stream/issues/403#issuecomment-479069043
|
||||
const chunks = [];
|
||||
try {
|
||||
for (var gzip_1 = __asyncValues(gzip), gzip_1_1; gzip_1_1 = yield gzip_1.next(), !gzip_1_1.done;) {
|
||||
const chunk = gzip_1_1.value;
|
||||
chunks.push(chunk);
|
||||
}
|
||||
}
|
||||
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
||||
finally {
|
||||
try {
|
||||
if (gzip_1_1 && !gzip_1_1.done && (_a = gzip_1.return)) yield _a.call(gzip_1);
|
||||
}
|
||||
finally { if (e_1) throw e_1.error; }
|
||||
}
|
||||
resolve(Buffer.concat(chunks));
|
||||
}));
|
||||
});
|
||||
}
|
||||
exports.createGZipFileInBuffer = createGZipFileInBuffer;
|
||||
//# sourceMappingURL=upload-gzip.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/upload-gzip.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/upload-gzip.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"upload-gzip.js","sourceRoot":"","sources":["../../src/internal/upload-gzip.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAwB;AACxB,2CAA4B;AAC5B,+BAA8B;AAC9B,MAAM,IAAI,GAAG,gBAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;AAE/B;;;;;GAKG;AACH,SAAsB,oBAAoB,CACxC,gBAAwB,EACxB,YAAoB;;QAEpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;YAC9B,MAAM,YAAY,GAAG,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,CAAA;YACvD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;YACzC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAS,EAAE;gBACnC,qIAAqI;gBACrI,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA;gBAC5C,OAAO,CAAC,IAAI,CAAC,CAAA;YACf,CAAC,CAAA,CAAC,CAAA;YACF,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;gBAC/B,sCAAsC;gBACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;gBAClB,MAAM,CAAA;YACR,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CAAA;AApBD,oDAoBC;AAED;;;;GAIG;AACH,SAAsB,sBAAsB,CAC1C,gBAAwB;;QAExB,OAAO,IAAI,OAAO,CAAC,CAAM,OAAO,EAAC,EAAE;;YACjC,MAAM,WAAW,GAAG,EAAE,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;YACzD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;YAC9B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACtB,8IAA8I;YAC9I,MAAM,MAAM,GAAG,EAAE,CAAA;;gBACjB,KAA0B,IAAA,SAAA,cAAA,IAAI,CAAA,UAAA;oBAAnB,MAAM,KAAK,iBAAA,CAAA;oBACpB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;iBACnB;;;;;;;;;YACD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QAChC,CAAC,CAAA,CAAC,CAAA;IACJ,CAAC;CAAA;AAdD,wDAcC"}
|
||||
48
node_modules/@actions/artifact/lib/internal/upload-http-client.d.ts
generated
vendored
Normal file
48
node_modules/@actions/artifact/lib/internal/upload-http-client.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { ArtifactResponse, UploadResults } from './contracts';
|
||||
import { UploadSpecification } from './upload-specification';
|
||||
import { UploadOptions } from './upload-options';
|
||||
export declare class UploadHttpClient {
|
||||
private uploadHttpManager;
|
||||
private statusReporter;
|
||||
constructor();
|
||||
/**
|
||||
* Creates a file container for the new artifact in the remote blob storage/file service
|
||||
* @param {string} artifactName Name of the artifact being created
|
||||
* @returns The response from the Artifact Service if the file container was successfully created
|
||||
*/
|
||||
createArtifactInFileContainer(artifactName: string, options?: UploadOptions | undefined): Promise<ArtifactResponse>;
|
||||
/**
|
||||
* Concurrently upload all of the files in chunks
|
||||
* @param {string} uploadUrl Base Url for the artifact that was created
|
||||
* @param {SearchResult[]} filesToUpload A list of information about the files being uploaded
|
||||
* @returns The size of all the files uploaded in bytes
|
||||
*/
|
||||
uploadArtifactToFileContainer(uploadUrl: string, filesToUpload: UploadSpecification[], options?: UploadOptions): Promise<UploadResults>;
|
||||
/**
|
||||
* Asynchronously uploads a file. The file is compressed and uploaded using GZip if it is determined to save space.
|
||||
* If the upload file is bigger than the max chunk size it will be uploaded via multiple calls
|
||||
* @param {number} httpClientIndex The index of the httpClient that is being used to make all of the calls
|
||||
* @param {UploadFileParameters} parameters Information about the file that needs to be uploaded
|
||||
* @returns The size of the file that was uploaded in bytes along with any failed uploads
|
||||
*/
|
||||
private uploadFileAsync;
|
||||
/**
|
||||
* Uploads a chunk of an individual file to the specified resourceUrl. If the upload fails and the status code
|
||||
* indicates a retryable status, we try to upload the chunk as well
|
||||
* @param {number} httpClientIndex The index of the httpClient being used to make all the necessary calls
|
||||
* @param {string} resourceUrl Url of the resource that the chunk will be uploaded to
|
||||
* @param {NodeJS.ReadableStream} openStream Stream of the file that will be uploaded
|
||||
* @param {number} start Starting byte index of file that the chunk belongs to
|
||||
* @param {number} end Ending byte index of file that the chunk belongs to
|
||||
* @param {number} uploadFileSize Total size of the file in bytes that is being uploaded
|
||||
* @param {boolean} isGzip Denotes if we are uploading a Gzip compressed stream
|
||||
* @param {number} totalFileSize Original total size of the file that is being uploaded
|
||||
* @returns if the chunk was successfully uploaded
|
||||
*/
|
||||
private uploadChunk;
|
||||
/**
|
||||
* Updates the size of the artifact from -1 which was initially set when the container was first created for the artifact.
|
||||
* Updating the size indicates that we are done uploading all the contents of the artifact
|
||||
*/
|
||||
patchArtifactSize(size: number, artifactName: string): Promise<void>;
|
||||
}
|
||||
379
node_modules/@actions/artifact/lib/internal/upload-http-client.js
generated
vendored
Normal file
379
node_modules/@actions/artifact/lib/internal/upload-http-client.js
generated
vendored
Normal file
|
|
@ -0,0 +1,379 @@
|
|||
"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 = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = __importStar(require("fs"));
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const tmp = __importStar(require("tmp-promise"));
|
||||
const stream = __importStar(require("stream"));
|
||||
const utils_1 = require("./utils");
|
||||
const config_variables_1 = require("./config-variables");
|
||||
const util_1 = require("util");
|
||||
const url_1 = require("url");
|
||||
const perf_hooks_1 = require("perf_hooks");
|
||||
const status_reporter_1 = require("./status-reporter");
|
||||
const http_client_1 = require("@actions/http-client");
|
||||
const http_manager_1 = require("./http-manager");
|
||||
const upload_gzip_1 = require("./upload-gzip");
|
||||
const requestUtils_1 = require("./requestUtils");
|
||||
const stat = util_1.promisify(fs.stat);
|
||||
class UploadHttpClient {
|
||||
constructor() {
|
||||
this.uploadHttpManager = new http_manager_1.HttpManager(config_variables_1.getUploadFileConcurrency(), '@actions/artifact-upload');
|
||||
this.statusReporter = new status_reporter_1.StatusReporter(10000);
|
||||
}
|
||||
/**
|
||||
* Creates a file container for the new artifact in the remote blob storage/file service
|
||||
* @param {string} artifactName Name of the artifact being created
|
||||
* @returns The response from the Artifact Service if the file container was successfully created
|
||||
*/
|
||||
createArtifactInFileContainer(artifactName, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const parameters = {
|
||||
Type: 'actions_storage',
|
||||
Name: artifactName
|
||||
};
|
||||
// calculate retention period
|
||||
if (options && options.retentionDays) {
|
||||
const maxRetentionStr = config_variables_1.getRetentionDays();
|
||||
parameters.RetentionDays = utils_1.getProperRetention(options.retentionDays, maxRetentionStr);
|
||||
}
|
||||
const data = JSON.stringify(parameters, null, 2);
|
||||
const artifactUrl = utils_1.getArtifactUrl();
|
||||
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
||||
const client = this.uploadHttpManager.getClient(0);
|
||||
const headers = utils_1.getUploadHeaders('application/json', false);
|
||||
// Extra information to display when a particular HTTP code is returned
|
||||
// If a 403 is returned when trying to create a file container, the customer has exceeded
|
||||
// their storage quota so no new artifact containers can be created
|
||||
const customErrorMessages = new Map([
|
||||
[
|
||||
http_client_1.HttpCodes.Forbidden,
|
||||
'Artifact storage quota has been hit. Unable to upload any new artifacts'
|
||||
],
|
||||
[
|
||||
http_client_1.HttpCodes.BadRequest,
|
||||
`The artifact name ${artifactName} is not valid. Request URL ${artifactUrl}`
|
||||
]
|
||||
]);
|
||||
const response = yield requestUtils_1.retryHttpClientRequest('Create Artifact Container', () => __awaiter(this, void 0, void 0, function* () { return client.post(artifactUrl, data, headers); }), customErrorMessages);
|
||||
const body = yield response.readBody();
|
||||
return JSON.parse(body);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Concurrently upload all of the files in chunks
|
||||
* @param {string} uploadUrl Base Url for the artifact that was created
|
||||
* @param {SearchResult[]} filesToUpload A list of information about the files being uploaded
|
||||
* @returns The size of all the files uploaded in bytes
|
||||
*/
|
||||
uploadArtifactToFileContainer(uploadUrl, filesToUpload, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const FILE_CONCURRENCY = config_variables_1.getUploadFileConcurrency();
|
||||
const MAX_CHUNK_SIZE = config_variables_1.getUploadChunkSize();
|
||||
core.debug(`File Concurrency: ${FILE_CONCURRENCY}, and Chunk Size: ${MAX_CHUNK_SIZE}`);
|
||||
const parameters = [];
|
||||
// by default, file uploads will continue if there is an error unless specified differently in the options
|
||||
let continueOnError = true;
|
||||
if (options) {
|
||||
if (options.continueOnError === false) {
|
||||
continueOnError = false;
|
||||
}
|
||||
}
|
||||
// prepare the necessary parameters to upload all the files
|
||||
for (const file of filesToUpload) {
|
||||
const resourceUrl = new url_1.URL(uploadUrl);
|
||||
resourceUrl.searchParams.append('itemPath', file.uploadFilePath);
|
||||
parameters.push({
|
||||
file: file.absoluteFilePath,
|
||||
resourceUrl: resourceUrl.toString(),
|
||||
maxChunkSize: MAX_CHUNK_SIZE,
|
||||
continueOnError
|
||||
});
|
||||
}
|
||||
const parallelUploads = [...new Array(FILE_CONCURRENCY).keys()];
|
||||
const failedItemsToReport = [];
|
||||
let currentFile = 0;
|
||||
let completedFiles = 0;
|
||||
let uploadFileSize = 0;
|
||||
let totalFileSize = 0;
|
||||
let abortPendingFileUploads = false;
|
||||
this.statusReporter.setTotalNumberOfFilesToProcess(filesToUpload.length);
|
||||
this.statusReporter.start();
|
||||
// only allow a certain amount of files to be uploaded at once, this is done to reduce potential errors
|
||||
yield Promise.all(parallelUploads.map((index) => __awaiter(this, void 0, void 0, function* () {
|
||||
while (currentFile < filesToUpload.length) {
|
||||
const currentFileParameters = parameters[currentFile];
|
||||
currentFile += 1;
|
||||
if (abortPendingFileUploads) {
|
||||
failedItemsToReport.push(currentFileParameters.file);
|
||||
continue;
|
||||
}
|
||||
const startTime = perf_hooks_1.performance.now();
|
||||
const uploadFileResult = yield this.uploadFileAsync(index, currentFileParameters);
|
||||
if (core.isDebug()) {
|
||||
core.debug(`File: ${++completedFiles}/${filesToUpload.length}. ${currentFileParameters.file} took ${(perf_hooks_1.performance.now() - startTime).toFixed(3)} milliseconds to finish upload`);
|
||||
}
|
||||
uploadFileSize += uploadFileResult.successfulUploadSize;
|
||||
totalFileSize += uploadFileResult.totalSize;
|
||||
if (uploadFileResult.isSuccess === false) {
|
||||
failedItemsToReport.push(currentFileParameters.file);
|
||||
if (!continueOnError) {
|
||||
// fail fast
|
||||
core.error(`aborting artifact upload`);
|
||||
abortPendingFileUploads = true;
|
||||
}
|
||||
}
|
||||
this.statusReporter.incrementProcessedCount();
|
||||
}
|
||||
})));
|
||||
this.statusReporter.stop();
|
||||
// done uploading, safety dispose all connections
|
||||
this.uploadHttpManager.disposeAndReplaceAllClients();
|
||||
core.info(`Total size of all the files uploaded is ${uploadFileSize} bytes`);
|
||||
return {
|
||||
uploadSize: uploadFileSize,
|
||||
totalSize: totalFileSize,
|
||||
failedItems: failedItemsToReport
|
||||
};
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Asynchronously uploads a file. The file is compressed and uploaded using GZip if it is determined to save space.
|
||||
* If the upload file is bigger than the max chunk size it will be uploaded via multiple calls
|
||||
* @param {number} httpClientIndex The index of the httpClient that is being used to make all of the calls
|
||||
* @param {UploadFileParameters} parameters Information about the file that needs to be uploaded
|
||||
* @returns The size of the file that was uploaded in bytes along with any failed uploads
|
||||
*/
|
||||
uploadFileAsync(httpClientIndex, parameters) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const totalFileSize = (yield stat(parameters.file)).size;
|
||||
let offset = 0;
|
||||
let isUploadSuccessful = true;
|
||||
let failedChunkSizes = 0;
|
||||
let uploadFileSize = 0;
|
||||
let isGzip = true;
|
||||
// the file that is being uploaded is less than 64k in size, to increase throughput and to minimize disk I/O
|
||||
// for creating a new GZip file, an in-memory buffer is used for compression
|
||||
if (totalFileSize < 65536) {
|
||||
const buffer = yield upload_gzip_1.createGZipFileInBuffer(parameters.file);
|
||||
//An open stream is needed in the event of a failure and we need to retry. If a NodeJS.ReadableStream is directly passed in,
|
||||
// it will not properly get reset to the start of the stream if a chunk upload needs to be retried
|
||||
let openUploadStream;
|
||||
if (totalFileSize < buffer.byteLength) {
|
||||
// compression did not help with reducing the size, use a readable stream from the original file for upload
|
||||
openUploadStream = () => fs.createReadStream(parameters.file);
|
||||
isGzip = false;
|
||||
uploadFileSize = totalFileSize;
|
||||
}
|
||||
else {
|
||||
// create a readable stream using a PassThrough stream that is both readable and writable
|
||||
openUploadStream = () => {
|
||||
const passThrough = new stream.PassThrough();
|
||||
passThrough.end(buffer);
|
||||
return passThrough;
|
||||
};
|
||||
uploadFileSize = buffer.byteLength;
|
||||
}
|
||||
const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, openUploadStream, 0, uploadFileSize - 1, uploadFileSize, isGzip, totalFileSize);
|
||||
if (!result) {
|
||||
// chunk failed to upload
|
||||
isUploadSuccessful = false;
|
||||
failedChunkSizes += uploadFileSize;
|
||||
core.warning(`Aborting upload for ${parameters.file} due to failure`);
|
||||
}
|
||||
return {
|
||||
isSuccess: isUploadSuccessful,
|
||||
successfulUploadSize: uploadFileSize - failedChunkSizes,
|
||||
totalSize: totalFileSize
|
||||
};
|
||||
}
|
||||
else {
|
||||
// the file that is being uploaded is greater than 64k in size, a temporary file gets created on disk using the
|
||||
// npm tmp-promise package and this file gets used to create a GZipped file
|
||||
const tempFile = yield tmp.file();
|
||||
// create a GZip file of the original file being uploaded, the original file should not be modified in any way
|
||||
uploadFileSize = yield upload_gzip_1.createGZipFileOnDisk(parameters.file, tempFile.path);
|
||||
let uploadFilePath = tempFile.path;
|
||||
// compression did not help with size reduction, use the original file for upload and delete the temp GZip file
|
||||
if (totalFileSize < uploadFileSize) {
|
||||
uploadFileSize = totalFileSize;
|
||||
uploadFilePath = parameters.file;
|
||||
isGzip = false;
|
||||
}
|
||||
let abortFileUpload = false;
|
||||
// upload only a single chunk at a time
|
||||
while (offset < uploadFileSize) {
|
||||
const chunkSize = Math.min(uploadFileSize - offset, parameters.maxChunkSize);
|
||||
// if an individual file is greater than 100MB (1024*1024*100) in size, display extra information about the upload status
|
||||
if (uploadFileSize > 104857600) {
|
||||
this.statusReporter.updateLargeFileStatus(parameters.file, offset, uploadFileSize);
|
||||
}
|
||||
const start = offset;
|
||||
const end = offset + chunkSize - 1;
|
||||
offset += parameters.maxChunkSize;
|
||||
if (abortFileUpload) {
|
||||
// if we don't want to continue in the event of an error, any pending upload chunks will be marked as failed
|
||||
failedChunkSizes += chunkSize;
|
||||
continue;
|
||||
}
|
||||
const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, () => fs.createReadStream(uploadFilePath, {
|
||||
start,
|
||||
end,
|
||||
autoClose: false
|
||||
}), start, end, uploadFileSize, isGzip, totalFileSize);
|
||||
if (!result) {
|
||||
// Chunk failed to upload, report as failed and do not continue uploading any more chunks for the file. It is possible that part of a chunk was
|
||||
// successfully uploaded so the server may report a different size for what was uploaded
|
||||
isUploadSuccessful = false;
|
||||
failedChunkSizes += chunkSize;
|
||||
core.warning(`Aborting upload for ${parameters.file} due to failure`);
|
||||
abortFileUpload = true;
|
||||
}
|
||||
}
|
||||
// Delete the temporary file that was created as part of the upload. If the temp file does not get manually deleted by
|
||||
// calling cleanup, it gets removed when the node process exits. For more info see: https://www.npmjs.com/package/tmp-promise#about
|
||||
yield tempFile.cleanup();
|
||||
return {
|
||||
isSuccess: isUploadSuccessful,
|
||||
successfulUploadSize: uploadFileSize - failedChunkSizes,
|
||||
totalSize: totalFileSize
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Uploads a chunk of an individual file to the specified resourceUrl. If the upload fails and the status code
|
||||
* indicates a retryable status, we try to upload the chunk as well
|
||||
* @param {number} httpClientIndex The index of the httpClient being used to make all the necessary calls
|
||||
* @param {string} resourceUrl Url of the resource that the chunk will be uploaded to
|
||||
* @param {NodeJS.ReadableStream} openStream Stream of the file that will be uploaded
|
||||
* @param {number} start Starting byte index of file that the chunk belongs to
|
||||
* @param {number} end Ending byte index of file that the chunk belongs to
|
||||
* @param {number} uploadFileSize Total size of the file in bytes that is being uploaded
|
||||
* @param {boolean} isGzip Denotes if we are uploading a Gzip compressed stream
|
||||
* @param {number} totalFileSize Original total size of the file that is being uploaded
|
||||
* @returns if the chunk was successfully uploaded
|
||||
*/
|
||||
uploadChunk(httpClientIndex, resourceUrl, openStream, start, end, uploadFileSize, isGzip, totalFileSize) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
// prepare all the necessary headers before making any http call
|
||||
const headers = utils_1.getUploadHeaders('application/octet-stream', true, isGzip, totalFileSize, end - start + 1, utils_1.getContentRange(start, end, uploadFileSize));
|
||||
const uploadChunkRequest = () => __awaiter(this, void 0, void 0, function* () {
|
||||
const client = this.uploadHttpManager.getClient(httpClientIndex);
|
||||
return yield client.sendStream('PUT', resourceUrl, openStream(), headers);
|
||||
});
|
||||
let retryCount = 0;
|
||||
const retryLimit = config_variables_1.getRetryLimit();
|
||||
// Increments the current retry count and then checks if the retry limit has been reached
|
||||
// If there have been too many retries, fail so the download stops
|
||||
const incrementAndCheckRetryLimit = (response) => {
|
||||
retryCount++;
|
||||
if (retryCount > retryLimit) {
|
||||
if (response) {
|
||||
utils_1.displayHttpDiagnostics(response);
|
||||
}
|
||||
core.info(`Retry limit has been reached for chunk at offset ${start} to ${resourceUrl}`);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const backOff = (retryAfterValue) => __awaiter(this, void 0, void 0, function* () {
|
||||
this.uploadHttpManager.disposeAndReplaceClient(httpClientIndex);
|
||||
if (retryAfterValue) {
|
||||
core.info(`Backoff due to too many requests, retry #${retryCount}. Waiting for ${retryAfterValue} milliseconds before continuing the upload`);
|
||||
yield utils_1.sleep(retryAfterValue);
|
||||
}
|
||||
else {
|
||||
const backoffTime = utils_1.getExponentialRetryTimeInMilliseconds(retryCount);
|
||||
core.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the upload at offset ${start}`);
|
||||
yield utils_1.sleep(backoffTime);
|
||||
}
|
||||
core.info(`Finished backoff for retry #${retryCount}, continuing with upload`);
|
||||
return;
|
||||
});
|
||||
// allow for failed chunks to be retried multiple times
|
||||
while (retryCount <= retryLimit) {
|
||||
let response;
|
||||
try {
|
||||
response = yield uploadChunkRequest();
|
||||
}
|
||||
catch (error) {
|
||||
// if an error is caught, it is usually indicative of a timeout so retry the upload
|
||||
core.info(`An error has been caught http-client index ${httpClientIndex}, retrying the upload`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
if (incrementAndCheckRetryLimit()) {
|
||||
return false;
|
||||
}
|
||||
yield backOff();
|
||||
continue;
|
||||
}
|
||||
// Always read the body of the response. There is potential for a resource leak if the body is not read which will
|
||||
// result in the connection remaining open along with unintended consequences when trying to dispose of the client
|
||||
yield response.readBody();
|
||||
if (utils_1.isSuccessStatusCode(response.message.statusCode)) {
|
||||
return true;
|
||||
}
|
||||
else if (utils_1.isRetryableStatusCode(response.message.statusCode)) {
|
||||
core.info(`A ${response.message.statusCode} status code has been received, will attempt to retry the upload`);
|
||||
if (incrementAndCheckRetryLimit(response)) {
|
||||
return false;
|
||||
}
|
||||
utils_1.isThrottledStatusCode(response.message.statusCode)
|
||||
? yield backOff(utils_1.tryGetRetryAfterValueTimeInMilliseconds(response.message.headers))
|
||||
: yield backOff();
|
||||
}
|
||||
else {
|
||||
core.error(`Unexpected response. Unable to upload chunk to ${resourceUrl}`);
|
||||
utils_1.displayHttpDiagnostics(response);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Updates the size of the artifact from -1 which was initially set when the container was first created for the artifact.
|
||||
* Updating the size indicates that we are done uploading all the contents of the artifact
|
||||
*/
|
||||
patchArtifactSize(size, artifactName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const resourceUrl = new url_1.URL(utils_1.getArtifactUrl());
|
||||
resourceUrl.searchParams.append('artifactName', artifactName);
|
||||
const parameters = { Size: size };
|
||||
const data = JSON.stringify(parameters, null, 2);
|
||||
core.debug(`URL is ${resourceUrl.toString()}`);
|
||||
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
||||
const client = this.uploadHttpManager.getClient(0);
|
||||
const headers = utils_1.getUploadHeaders('application/json', false);
|
||||
// Extra information to display when a particular HTTP code is returned
|
||||
const customErrorMessages = new Map([
|
||||
[
|
||||
http_client_1.HttpCodes.NotFound,
|
||||
`An Artifact with the name ${artifactName} was not found`
|
||||
]
|
||||
]);
|
||||
// TODO retry for all possible response codes, the artifact upload is pretty much complete so it at all costs we should try to finish this
|
||||
const response = yield requestUtils_1.retryHttpClientRequest('Finalize artifact upload', () => __awaiter(this, void 0, void 0, function* () { return client.patch(resourceUrl.toString(), data, headers); }), customErrorMessages);
|
||||
yield response.readBody();
|
||||
core.debug(`Artifact ${artifactName} has been successfully uploaded, total size in bytes: ${size}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.UploadHttpClient = UploadHttpClient;
|
||||
//# sourceMappingURL=upload-http-client.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/upload-http-client.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/upload-http-client.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
34
node_modules/@actions/artifact/lib/internal/upload-options.d.ts
generated
vendored
Normal file
34
node_modules/@actions/artifact/lib/internal/upload-options.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
export interface UploadOptions {
|
||||
/**
|
||||
* Indicates if the artifact upload should continue if file or chunk fails to upload from any error.
|
||||
* If there is a error during upload, a partial artifact will always be associated and available for
|
||||
* download at the end. The size reported will be the amount of storage that the user or org will be
|
||||
* charged for the partial artifact. Defaults to true if not specified
|
||||
*
|
||||
* If set to false, and an error is encountered, all other uploads will stop and any files or chunks
|
||||
* that were queued will not be attempted to be uploaded. The partial artifact available will only
|
||||
* include files and chunks up until the failure
|
||||
*
|
||||
* If set to true and an error is encountered, the failed file will be skipped and ignored and all
|
||||
* other queued files will be attempted to be uploaded. The partial artifact at the end will have all
|
||||
* files with the exception of the problematic files(s)/chunks(s) that failed to upload
|
||||
*
|
||||
*/
|
||||
continueOnError?: boolean;
|
||||
/**
|
||||
* Duration after which artifact will expire in days.
|
||||
*
|
||||
* By default artifact expires after 90 days:
|
||||
* https://docs.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts#downloading-and-deleting-artifacts-after-a-workflow-run-is-complete
|
||||
*
|
||||
* Use this option to override the default expiry.
|
||||
*
|
||||
* Min value: 1
|
||||
* Max value: 90 unless changed by repository setting
|
||||
*
|
||||
* If this is set to a greater value than the retention settings allowed, the retention on artifacts
|
||||
* will be reduced to match the max value allowed on server, and the upload process will continue. An
|
||||
* input of 0 assumes default retention setting.
|
||||
*/
|
||||
retentionDays?: number;
|
||||
}
|
||||
3
node_modules/@actions/artifact/lib/internal/upload-options.js
generated
vendored
Normal file
3
node_modules/@actions/artifact/lib/internal/upload-options.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=upload-options.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/upload-options.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/upload-options.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"upload-options.js","sourceRoot":"","sources":["../../src/internal/upload-options.ts"],"names":[],"mappings":""}
|
||||
19
node_modules/@actions/artifact/lib/internal/upload-response.d.ts
generated
vendored
Normal file
19
node_modules/@actions/artifact/lib/internal/upload-response.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
export interface UploadResponse {
|
||||
/**
|
||||
* The name of the artifact that was uploaded
|
||||
*/
|
||||
artifactName: string;
|
||||
/**
|
||||
* A list of all items that are meant to be uploaded as part of the artifact
|
||||
*/
|
||||
artifactItems: string[];
|
||||
/**
|
||||
* Total size of the artifact in bytes that was uploaded
|
||||
*/
|
||||
size: number;
|
||||
/**
|
||||
* A list of items that were not uploaded as part of the artifact (includes queued items that were not uploaded if
|
||||
* continueOnError is set to false). This is a subset of artifactItems.
|
||||
*/
|
||||
failedItems: string[];
|
||||
}
|
||||
3
node_modules/@actions/artifact/lib/internal/upload-response.js
generated
vendored
Normal file
3
node_modules/@actions/artifact/lib/internal/upload-response.js
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=upload-response.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/upload-response.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/upload-response.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"upload-response.js","sourceRoot":"","sources":["../../src/internal/upload-response.ts"],"names":[],"mappings":""}
|
||||
11
node_modules/@actions/artifact/lib/internal/upload-specification.d.ts
generated
vendored
Normal file
11
node_modules/@actions/artifact/lib/internal/upload-specification.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
export interface UploadSpecification {
|
||||
absoluteFilePath: string;
|
||||
uploadFilePath: string;
|
||||
}
|
||||
/**
|
||||
* Creates a specification that describes how each file that is part of the artifact will be uploaded
|
||||
* @param artifactName the name of the artifact being uploaded. Used during upload to denote where the artifact is stored on the server
|
||||
* @param rootDirectory an absolute file path that denotes the path that should be removed from the beginning of each artifact file
|
||||
* @param artifactFiles a list of absolute file paths that denote what should be uploaded as part of the artifact
|
||||
*/
|
||||
export declare function getUploadSpecification(artifactName: string, rootDirectory: string, artifactFiles: string[]): UploadSpecification[];
|
||||
88
node_modules/@actions/artifact/lib/internal/upload-specification.js
generated
vendored
Normal file
88
node_modules/@actions/artifact/lib/internal/upload-specification.js
generated
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
"use strict";
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = __importStar(require("fs"));
|
||||
const core_1 = require("@actions/core");
|
||||
const path_1 = require("path");
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* Creates a specification that describes how each file that is part of the artifact will be uploaded
|
||||
* @param artifactName the name of the artifact being uploaded. Used during upload to denote where the artifact is stored on the server
|
||||
* @param rootDirectory an absolute file path that denotes the path that should be removed from the beginning of each artifact file
|
||||
* @param artifactFiles a list of absolute file paths that denote what should be uploaded as part of the artifact
|
||||
*/
|
||||
function getUploadSpecification(artifactName, rootDirectory, artifactFiles) {
|
||||
utils_1.checkArtifactName(artifactName);
|
||||
const specifications = [];
|
||||
if (!fs.existsSync(rootDirectory)) {
|
||||
throw new Error(`Provided rootDirectory ${rootDirectory} does not exist`);
|
||||
}
|
||||
if (!fs.lstatSync(rootDirectory).isDirectory()) {
|
||||
throw new Error(`Provided rootDirectory ${rootDirectory} is not a valid directory`);
|
||||
}
|
||||
// Normalize and resolve, this allows for either absolute or relative paths to be used
|
||||
rootDirectory = path_1.normalize(rootDirectory);
|
||||
rootDirectory = path_1.resolve(rootDirectory);
|
||||
/*
|
||||
Example to demonstrate behavior
|
||||
|
||||
Input:
|
||||
artifactName: my-artifact
|
||||
rootDirectory: '/home/user/files/plz-upload'
|
||||
artifactFiles: [
|
||||
'/home/user/files/plz-upload/file1.txt',
|
||||
'/home/user/files/plz-upload/file2.txt',
|
||||
'/home/user/files/plz-upload/dir/file3.txt'
|
||||
]
|
||||
|
||||
Output:
|
||||
specifications: [
|
||||
['/home/user/files/plz-upload/file1.txt', 'my-artifact/file1.txt'],
|
||||
['/home/user/files/plz-upload/file1.txt', 'my-artifact/file2.txt'],
|
||||
['/home/user/files/plz-upload/file1.txt', 'my-artifact/dir/file3.txt']
|
||||
]
|
||||
*/
|
||||
for (let file of artifactFiles) {
|
||||
if (!fs.existsSync(file)) {
|
||||
throw new Error(`File ${file} does not exist`);
|
||||
}
|
||||
if (!fs.lstatSync(file).isDirectory()) {
|
||||
// Normalize and resolve, this allows for either absolute or relative paths to be used
|
||||
file = path_1.normalize(file);
|
||||
file = path_1.resolve(file);
|
||||
if (!file.startsWith(rootDirectory)) {
|
||||
throw new Error(`The rootDirectory: ${rootDirectory} is not a parent directory of the file: ${file}`);
|
||||
}
|
||||
// Check for forbidden characters in file paths that will be rejected during upload
|
||||
const uploadPath = file.replace(rootDirectory, '');
|
||||
utils_1.checkArtifactFilePath(uploadPath);
|
||||
/*
|
||||
uploadFilePath denotes where the file will be uploaded in the file container on the server. During a run, if multiple artifacts are uploaded, they will all
|
||||
be saved in the same container. The artifact name is used as the root directory in the container to separate and distinguish uploaded artifacts
|
||||
|
||||
path.join handles all the following cases and would return 'artifact-name/file-to-upload.txt
|
||||
join('artifact-name/', 'file-to-upload.txt')
|
||||
join('artifact-name/', '/file-to-upload.txt')
|
||||
join('artifact-name', 'file-to-upload.txt')
|
||||
join('artifact-name', '/file-to-upload.txt')
|
||||
*/
|
||||
specifications.push({
|
||||
absoluteFilePath: file,
|
||||
uploadFilePath: path_1.join(artifactName, uploadPath)
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Directories are rejected by the server during upload
|
||||
core_1.debug(`Removing ${file} from rawSearchResults because it is a directory`);
|
||||
}
|
||||
}
|
||||
return specifications;
|
||||
}
|
||||
exports.getUploadSpecification = getUploadSpecification;
|
||||
//# sourceMappingURL=upload-specification.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/upload-specification.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/upload-specification.js.map
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"upload-specification.js","sourceRoot":"","sources":["../../src/internal/upload-specification.ts"],"names":[],"mappings":";;;;;;;;;AAAA,uCAAwB;AACxB,wCAAmC;AACnC,+BAA6C;AAC7C,mCAAgE;AAOhE;;;;;GAKG;AACH,SAAgB,sBAAsB,CACpC,YAAoB,EACpB,aAAqB,EACrB,aAAuB;IAEvB,yBAAiB,CAAC,YAAY,CAAC,CAAA;IAE/B,MAAM,cAAc,GAA0B,EAAE,CAAA;IAEhD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;QACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,aAAa,iBAAiB,CAAC,CAAA;KAC1E;IACD,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,EAAE;QAC9C,MAAM,IAAI,KAAK,CACb,0BAA0B,aAAa,2BAA2B,CACnE,CAAA;KACF;IACD,sFAAsF;IACtF,aAAa,GAAG,gBAAS,CAAC,aAAa,CAAC,CAAA;IACxC,aAAa,GAAG,cAAO,CAAC,aAAa,CAAC,CAAA;IAEtC;;;;;;;;;;;;;;;;;;MAkBE;IACF,KAAK,IAAI,IAAI,IAAI,aAAa,EAAE;QAC9B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;YACxB,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,iBAAiB,CAAC,CAAA;SAC/C;QACD,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;YACrC,sFAAsF;YACtF,IAAI,GAAG,gBAAS,CAAC,IAAI,CAAC,CAAA;YACtB,IAAI,GAAG,cAAO,CAAC,IAAI,CAAC,CAAA;YACpB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE;gBACnC,MAAM,IAAI,KAAK,CACb,sBAAsB,aAAa,2CAA2C,IAAI,EAAE,CACrF,CAAA;aACF;YAED,mFAAmF;YACnF,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;YAClD,6BAAqB,CAAC,UAAU,CAAC,CAAA;YAEjC;;;;;;;;;cASE;YACF,cAAc,CAAC,IAAI,CAAC;gBAClB,gBAAgB,EAAE,IAAI;gBACtB,cAAc,EAAE,WAAI,CAAC,YAAY,EAAE,UAAU,CAAC;aAC/C,CAAC,CAAA;SACH;aAAM;YACL,uDAAuD;YACvD,YAAK,CAAC,YAAY,IAAI,kDAAkD,CAAC,CAAA;SAC1E;KACF;IACD,OAAO,cAAc,CAAA;AACvB,CAAC;AA9ED,wDA8EC"}
|
||||
74
node_modules/@actions/artifact/lib/internal/utils.d.ts
generated
vendored
Normal file
74
node_modules/@actions/artifact/lib/internal/utils.d.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/// <reference types="node" />
|
||||
import { HttpClient } from '@actions/http-client';
|
||||
import { IHeaders, IHttpClientResponse } from '@actions/http-client/interfaces';
|
||||
import { IncomingHttpHeaders } from 'http';
|
||||
/**
|
||||
* Returns a retry time in milliseconds that exponentially gets larger
|
||||
* depending on the amount of retries that have been attempted
|
||||
*/
|
||||
export declare function getExponentialRetryTimeInMilliseconds(retryCount: number): number;
|
||||
/**
|
||||
* Parses a env variable that is a number
|
||||
*/
|
||||
export declare function parseEnvNumber(key: string): number | undefined;
|
||||
/**
|
||||
* Various utility functions to help with the necessary API calls
|
||||
*/
|
||||
export declare function getApiVersion(): string;
|
||||
export declare function isSuccessStatusCode(statusCode?: number): boolean;
|
||||
export declare function isForbiddenStatusCode(statusCode?: number): boolean;
|
||||
export declare function isRetryableStatusCode(statusCode: number | undefined): boolean;
|
||||
export declare function isThrottledStatusCode(statusCode?: number): boolean;
|
||||
/**
|
||||
* Attempts to get the retry-after value from a set of http headers. The retry time
|
||||
* is originally denoted in seconds, so if present, it is converted to milliseconds
|
||||
* @param headers all the headers received when making an http call
|
||||
*/
|
||||
export declare function tryGetRetryAfterValueTimeInMilliseconds(headers: IncomingHttpHeaders): number | undefined;
|
||||
export declare function getContentRange(start: number, end: number, total: number): string;
|
||||
/**
|
||||
* Sets all the necessary headers when downloading an artifact
|
||||
* @param {string} contentType the type of content being uploaded
|
||||
* @param {boolean} isKeepAlive is the same connection being used to make multiple calls
|
||||
* @param {boolean} acceptGzip can we accept a gzip encoded response
|
||||
* @param {string} acceptType the type of content that we can accept
|
||||
* @returns appropriate headers to make a specific http call during artifact download
|
||||
*/
|
||||
export declare function getDownloadHeaders(contentType: string, isKeepAlive?: boolean, acceptGzip?: boolean): IHeaders;
|
||||
/**
|
||||
* Sets all the necessary headers when uploading an artifact
|
||||
* @param {string} contentType the type of content being uploaded
|
||||
* @param {boolean} isKeepAlive is the same connection being used to make multiple calls
|
||||
* @param {boolean} isGzip is the connection being used to upload GZip compressed content
|
||||
* @param {number} uncompressedLength the original size of the content if something is being uploaded that has been compressed
|
||||
* @param {number} contentLength the length of the content that is being uploaded
|
||||
* @param {string} contentRange the range of the content that is being uploaded
|
||||
* @returns appropriate headers to make a specific http call during artifact upload
|
||||
*/
|
||||
export declare function getUploadHeaders(contentType: string, isKeepAlive?: boolean, isGzip?: boolean, uncompressedLength?: number, contentLength?: number, contentRange?: string): IHeaders;
|
||||
export declare function createHttpClient(userAgent: string): HttpClient;
|
||||
export declare function getArtifactUrl(): string;
|
||||
/**
|
||||
* Uh oh! Something might have gone wrong during either upload or download. The IHtttpClientResponse object contains information
|
||||
* about the http call that was made by the actions http client. This information might be useful to display for diagnostic purposes, but
|
||||
* this entire object is really big and most of the information is not really useful. This function takes the response object and displays only
|
||||
* the information that we want.
|
||||
*
|
||||
* Certain information such as the TLSSocket and the Readable state are not really useful for diagnostic purposes so they can be avoided.
|
||||
* Other information such as the headers, the response code and message might be useful, so this is displayed.
|
||||
*/
|
||||
export declare function displayHttpDiagnostics(response: IHttpClientResponse): void;
|
||||
/**
|
||||
* Scans the name of the artifact to make sure there are no illegal characters
|
||||
*/
|
||||
export declare function checkArtifactName(name: string): void;
|
||||
/**
|
||||
* Scans the name of the filePath used to make sure there are no illegal characters
|
||||
*/
|
||||
export declare function checkArtifactFilePath(path: string): void;
|
||||
export declare function createDirectoriesForArtifact(directories: string[]): Promise<void>;
|
||||
export declare function createEmptyFilesForArtifact(emptyFilesToCreate: string[]): Promise<void>;
|
||||
export declare function getFileSize(filePath: string): Promise<number>;
|
||||
export declare function rmFile(filePath: string): Promise<void>;
|
||||
export declare function getProperRetention(retentionInput: number, retentionSetting: string | undefined): number;
|
||||
export declare function sleep(milliseconds: number): Promise<void>;
|
||||
304
node_modules/@actions/artifact/lib/internal/utils.js
generated
vendored
Normal file
304
node_modules/@actions/artifact/lib/internal/utils.js
generated
vendored
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
"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 core_1 = require("@actions/core");
|
||||
const fs_1 = require("fs");
|
||||
const http_client_1 = require("@actions/http-client");
|
||||
const auth_1 = require("@actions/http-client/auth");
|
||||
const config_variables_1 = require("./config-variables");
|
||||
/**
|
||||
* Returns a retry time in milliseconds that exponentially gets larger
|
||||
* depending on the amount of retries that have been attempted
|
||||
*/
|
||||
function getExponentialRetryTimeInMilliseconds(retryCount) {
|
||||
if (retryCount < 0) {
|
||||
throw new Error('RetryCount should not be negative');
|
||||
}
|
||||
else if (retryCount === 0) {
|
||||
return config_variables_1.getInitialRetryIntervalInMilliseconds();
|
||||
}
|
||||
const minTime = config_variables_1.getInitialRetryIntervalInMilliseconds() * config_variables_1.getRetryMultiplier() * retryCount;
|
||||
const maxTime = minTime * config_variables_1.getRetryMultiplier();
|
||||
// returns a random number between the minTime (inclusive) and the maxTime (exclusive)
|
||||
return Math.random() * (maxTime - minTime) + minTime;
|
||||
}
|
||||
exports.getExponentialRetryTimeInMilliseconds = getExponentialRetryTimeInMilliseconds;
|
||||
/**
|
||||
* Parses a env variable that is a number
|
||||
*/
|
||||
function parseEnvNumber(key) {
|
||||
const value = Number(process.env[key]);
|
||||
if (Number.isNaN(value) || value < 0) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
exports.parseEnvNumber = parseEnvNumber;
|
||||
/**
|
||||
* Various utility functions to help with the necessary API calls
|
||||
*/
|
||||
function getApiVersion() {
|
||||
return '6.0-preview';
|
||||
}
|
||||
exports.getApiVersion = getApiVersion;
|
||||
function isSuccessStatusCode(statusCode) {
|
||||
if (!statusCode) {
|
||||
return false;
|
||||
}
|
||||
return statusCode >= 200 && statusCode < 300;
|
||||
}
|
||||
exports.isSuccessStatusCode = isSuccessStatusCode;
|
||||
function isForbiddenStatusCode(statusCode) {
|
||||
if (!statusCode) {
|
||||
return false;
|
||||
}
|
||||
return statusCode === http_client_1.HttpCodes.Forbidden;
|
||||
}
|
||||
exports.isForbiddenStatusCode = isForbiddenStatusCode;
|
||||
function isRetryableStatusCode(statusCode) {
|
||||
if (!statusCode) {
|
||||
return false;
|
||||
}
|
||||
const retryableStatusCodes = [
|
||||
http_client_1.HttpCodes.BadGateway,
|
||||
http_client_1.HttpCodes.ServiceUnavailable,
|
||||
http_client_1.HttpCodes.GatewayTimeout,
|
||||
http_client_1.HttpCodes.TooManyRequests,
|
||||
413 // Payload Too Large
|
||||
];
|
||||
return retryableStatusCodes.includes(statusCode);
|
||||
}
|
||||
exports.isRetryableStatusCode = isRetryableStatusCode;
|
||||
function isThrottledStatusCode(statusCode) {
|
||||
if (!statusCode) {
|
||||
return false;
|
||||
}
|
||||
return statusCode === http_client_1.HttpCodes.TooManyRequests;
|
||||
}
|
||||
exports.isThrottledStatusCode = isThrottledStatusCode;
|
||||
/**
|
||||
* Attempts to get the retry-after value from a set of http headers. The retry time
|
||||
* is originally denoted in seconds, so if present, it is converted to milliseconds
|
||||
* @param headers all the headers received when making an http call
|
||||
*/
|
||||
function tryGetRetryAfterValueTimeInMilliseconds(headers) {
|
||||
if (headers['retry-after']) {
|
||||
const retryTime = Number(headers['retry-after']);
|
||||
if (!isNaN(retryTime)) {
|
||||
core_1.info(`Retry-After header is present with a value of ${retryTime}`);
|
||||
return retryTime * 1000;
|
||||
}
|
||||
core_1.info(`Returned retry-after header value: ${retryTime} is non-numeric and cannot be used`);
|
||||
return undefined;
|
||||
}
|
||||
core_1.info(`No retry-after header was found. Dumping all headers for diagnostic purposes`);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(headers);
|
||||
return undefined;
|
||||
}
|
||||
exports.tryGetRetryAfterValueTimeInMilliseconds = tryGetRetryAfterValueTimeInMilliseconds;
|
||||
function getContentRange(start, end, total) {
|
||||
// Format: `bytes start-end/fileSize
|
||||
// start and end are inclusive
|
||||
// For a 200 byte chunk starting at byte 0:
|
||||
// Content-Range: bytes 0-199/200
|
||||
return `bytes ${start}-${end}/${total}`;
|
||||
}
|
||||
exports.getContentRange = getContentRange;
|
||||
/**
|
||||
* Sets all the necessary headers when downloading an artifact
|
||||
* @param {string} contentType the type of content being uploaded
|
||||
* @param {boolean} isKeepAlive is the same connection being used to make multiple calls
|
||||
* @param {boolean} acceptGzip can we accept a gzip encoded response
|
||||
* @param {string} acceptType the type of content that we can accept
|
||||
* @returns appropriate headers to make a specific http call during artifact download
|
||||
*/
|
||||
function getDownloadHeaders(contentType, isKeepAlive, acceptGzip) {
|
||||
const requestOptions = {};
|
||||
if (contentType) {
|
||||
requestOptions['Content-Type'] = contentType;
|
||||
}
|
||||
if (isKeepAlive) {
|
||||
requestOptions['Connection'] = 'Keep-Alive';
|
||||
// keep alive for at least 10 seconds before closing the connection
|
||||
requestOptions['Keep-Alive'] = '10';
|
||||
}
|
||||
if (acceptGzip) {
|
||||
// if we are expecting a response with gzip encoding, it should be using an octet-stream in the accept header
|
||||
requestOptions['Accept-Encoding'] = 'gzip';
|
||||
requestOptions['Accept'] = `application/octet-stream;api-version=${getApiVersion()}`;
|
||||
}
|
||||
else {
|
||||
// default to application/json if we are not working with gzip content
|
||||
requestOptions['Accept'] = `application/json;api-version=${getApiVersion()}`;
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
exports.getDownloadHeaders = getDownloadHeaders;
|
||||
/**
|
||||
* Sets all the necessary headers when uploading an artifact
|
||||
* @param {string} contentType the type of content being uploaded
|
||||
* @param {boolean} isKeepAlive is the same connection being used to make multiple calls
|
||||
* @param {boolean} isGzip is the connection being used to upload GZip compressed content
|
||||
* @param {number} uncompressedLength the original size of the content if something is being uploaded that has been compressed
|
||||
* @param {number} contentLength the length of the content that is being uploaded
|
||||
* @param {string} contentRange the range of the content that is being uploaded
|
||||
* @returns appropriate headers to make a specific http call during artifact upload
|
||||
*/
|
||||
function getUploadHeaders(contentType, isKeepAlive, isGzip, uncompressedLength, contentLength, contentRange) {
|
||||
const requestOptions = {};
|
||||
requestOptions['Accept'] = `application/json;api-version=${getApiVersion()}`;
|
||||
if (contentType) {
|
||||
requestOptions['Content-Type'] = contentType;
|
||||
}
|
||||
if (isKeepAlive) {
|
||||
requestOptions['Connection'] = 'Keep-Alive';
|
||||
// keep alive for at least 10 seconds before closing the connection
|
||||
requestOptions['Keep-Alive'] = '10';
|
||||
}
|
||||
if (isGzip) {
|
||||
requestOptions['Content-Encoding'] = 'gzip';
|
||||
requestOptions['x-tfs-filelength'] = uncompressedLength;
|
||||
}
|
||||
if (contentLength) {
|
||||
requestOptions['Content-Length'] = contentLength;
|
||||
}
|
||||
if (contentRange) {
|
||||
requestOptions['Content-Range'] = contentRange;
|
||||
}
|
||||
return requestOptions;
|
||||
}
|
||||
exports.getUploadHeaders = getUploadHeaders;
|
||||
function createHttpClient(userAgent) {
|
||||
return new http_client_1.HttpClient(userAgent, [
|
||||
new auth_1.BearerCredentialHandler(config_variables_1.getRuntimeToken())
|
||||
]);
|
||||
}
|
||||
exports.createHttpClient = createHttpClient;
|
||||
function getArtifactUrl() {
|
||||
const artifactUrl = `${config_variables_1.getRuntimeUrl()}_apis/pipelines/workflows/${config_variables_1.getWorkFlowRunId()}/artifacts?api-version=${getApiVersion()}`;
|
||||
core_1.debug(`Artifact Url: ${artifactUrl}`);
|
||||
return artifactUrl;
|
||||
}
|
||||
exports.getArtifactUrl = getArtifactUrl;
|
||||
/**
|
||||
* Uh oh! Something might have gone wrong during either upload or download. The IHtttpClientResponse object contains information
|
||||
* about the http call that was made by the actions http client. This information might be useful to display for diagnostic purposes, but
|
||||
* this entire object is really big and most of the information is not really useful. This function takes the response object and displays only
|
||||
* the information that we want.
|
||||
*
|
||||
* Certain information such as the TLSSocket and the Readable state are not really useful for diagnostic purposes so they can be avoided.
|
||||
* Other information such as the headers, the response code and message might be useful, so this is displayed.
|
||||
*/
|
||||
function displayHttpDiagnostics(response) {
|
||||
core_1.info(`##### Begin Diagnostic HTTP information #####
|
||||
Status Code: ${response.message.statusCode}
|
||||
Status Message: ${response.message.statusMessage}
|
||||
Header Information: ${JSON.stringify(response.message.headers, undefined, 2)}
|
||||
###### End Diagnostic HTTP information ######`);
|
||||
}
|
||||
exports.displayHttpDiagnostics = displayHttpDiagnostics;
|
||||
/**
|
||||
* Invalid characters that cannot be in the artifact name or an uploaded file. Will be rejected
|
||||
* from the server if attempted to be sent over. These characters are not allowed due to limitations with certain
|
||||
* file systems such as NTFS. To maintain platform-agnostic behavior, all characters that are not supported by an
|
||||
* individual filesystem/platform will not be supported on all fileSystems/platforms
|
||||
*
|
||||
* FilePaths can include characters such as \ and / which are not permitted in the artifact name alone
|
||||
*/
|
||||
const invalidArtifactFilePathCharacters = ['"', ':', '<', '>', '|', '*', '?'];
|
||||
const invalidArtifactNameCharacters = [
|
||||
...invalidArtifactFilePathCharacters,
|
||||
'\\',
|
||||
'/'
|
||||
];
|
||||
/**
|
||||
* Scans the name of the artifact to make sure there are no illegal characters
|
||||
*/
|
||||
function checkArtifactName(name) {
|
||||
if (!name) {
|
||||
throw new Error(`Artifact name: ${name}, is incorrectly provided`);
|
||||
}
|
||||
for (const invalidChar of invalidArtifactNameCharacters) {
|
||||
if (name.includes(invalidChar)) {
|
||||
throw new Error(`Artifact name is not valid: ${name}. Contains character: "${invalidChar}". Invalid artifact name characters include: ${invalidArtifactNameCharacters.toString()}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.checkArtifactName = checkArtifactName;
|
||||
/**
|
||||
* Scans the name of the filePath used to make sure there are no illegal characters
|
||||
*/
|
||||
function checkArtifactFilePath(path) {
|
||||
if (!path) {
|
||||
throw new Error(`Artifact path: ${path}, is incorrectly provided`);
|
||||
}
|
||||
for (const invalidChar of invalidArtifactFilePathCharacters) {
|
||||
if (path.includes(invalidChar)) {
|
||||
throw new Error(`Artifact path is not valid: ${path}. Contains character: "${invalidChar}". Invalid characters include: ${invalidArtifactFilePathCharacters.toString()}.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.checkArtifactFilePath = checkArtifactFilePath;
|
||||
function createDirectoriesForArtifact(directories) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const directory of directories) {
|
||||
yield fs_1.promises.mkdir(directory, {
|
||||
recursive: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.createDirectoriesForArtifact = createDirectoriesForArtifact;
|
||||
function createEmptyFilesForArtifact(emptyFilesToCreate) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const filePath of emptyFilesToCreate) {
|
||||
yield (yield fs_1.promises.open(filePath, 'w')).close();
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.createEmptyFilesForArtifact = createEmptyFilesForArtifact;
|
||||
function getFileSize(filePath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const stats = yield fs_1.promises.stat(filePath);
|
||||
core_1.debug(`${filePath} size:(${stats.size}) blksize:(${stats.blksize}) blocks:(${stats.blocks})`);
|
||||
return stats.size;
|
||||
});
|
||||
}
|
||||
exports.getFileSize = getFileSize;
|
||||
function rmFile(filePath) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield fs_1.promises.unlink(filePath);
|
||||
});
|
||||
}
|
||||
exports.rmFile = rmFile;
|
||||
function getProperRetention(retentionInput, retentionSetting) {
|
||||
if (retentionInput < 0) {
|
||||
throw new Error('Invalid retention, minimum value is 1.');
|
||||
}
|
||||
let retention = retentionInput;
|
||||
if (retentionSetting) {
|
||||
const maxRetention = parseInt(retentionSetting);
|
||||
if (!isNaN(maxRetention) && maxRetention < retention) {
|
||||
core_1.warning(`Retention days is greater than the max value allowed by the repository setting, reduce retention to ${maxRetention} days`);
|
||||
retention = maxRetention;
|
||||
}
|
||||
}
|
||||
return retention;
|
||||
}
|
||||
exports.getProperRetention = getProperRetention;
|
||||
function sleep(milliseconds) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
});
|
||||
}
|
||||
exports.sleep = sleep;
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@actions/artifact/lib/internal/utils.js.map
generated
vendored
Normal file
1
node_modules/@actions/artifact/lib/internal/utils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue