|
|
|
@@ -3509,7 +3509,6 @@ class DefaultArtifactClient {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
downloadArtifact(name, path, options) {
|
|
|
|
downloadArtifact(name, path, options) {
|
|
|
|
var _a;
|
|
|
|
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const downloadHttpClient = new download_http_client_1.DownloadHttpClient();
|
|
|
|
const downloadHttpClient = new download_http_client_1.DownloadHttpClient();
|
|
|
|
const artifacts = yield downloadHttpClient.listArtifacts();
|
|
|
|
const artifacts = yield downloadHttpClient.listArtifacts();
|
|
|
|
@@ -3529,7 +3528,7 @@ class DefaultArtifactClient {
|
|
|
|
path = path_1.normalize(path);
|
|
|
|
path = path_1.normalize(path);
|
|
|
|
path = path_1.resolve(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
|
|
|
|
// 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, ((_a = options) === null || _a === void 0 ? void 0 : _a.createArtifactFolder) || false);
|
|
|
|
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) {
|
|
|
|
if (downloadSpecification.filesToDownload.length === 0) {
|
|
|
|
core.info(`No downloadable files were found for the artifact: ${artifactToDownload.name}`);
|
|
|
|
core.info(`No downloadable files were found for the artifact: ${artifactToDownload.name}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -3603,7 +3602,7 @@ exports.getUploadFileConcurrency = getUploadFileConcurrency;
|
|
|
|
// When uploading large files that can't be uploaded with a single http call, this controls
|
|
|
|
// When uploading large files that can't be uploaded with a single http call, this controls
|
|
|
|
// the chunk size that is used during upload
|
|
|
|
// the chunk size that is used during upload
|
|
|
|
function getUploadChunkSize() {
|
|
|
|
function getUploadChunkSize() {
|
|
|
|
return 4 * 1024 * 1024; // 4 MB Chunks
|
|
|
|
return 8 * 1024 * 1024; // 8 MB Chunks
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exports.getUploadChunkSize = getUploadChunkSize;
|
|
|
|
exports.getUploadChunkSize = getUploadChunkSize;
|
|
|
|
// The maximum number of retries that can be attempted before an upload or download fails
|
|
|
|
// The maximum number of retries that can be attempted before an upload or download fails
|
|
|
|
@@ -4557,11 +4556,12 @@ const utils_1 = __webpack_require__(870);
|
|
|
|
* Used for managing http clients during either upload or download
|
|
|
|
* Used for managing http clients during either upload or download
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
class HttpManager {
|
|
|
|
class HttpManager {
|
|
|
|
constructor(clientCount) {
|
|
|
|
constructor(clientCount, userAgent) {
|
|
|
|
if (clientCount < 1) {
|
|
|
|
if (clientCount < 1) {
|
|
|
|
throw new Error('There must be at least one client');
|
|
|
|
throw new Error('There must be at least one client');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.clients = new Array(clientCount).fill(utils_1.createHttpClient());
|
|
|
|
this.userAgent = userAgent;
|
|
|
|
|
|
|
|
this.clients = new Array(clientCount).fill(utils_1.createHttpClient(userAgent));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
getClient(index) {
|
|
|
|
getClient(index) {
|
|
|
|
return this.clients[index];
|
|
|
|
return this.clients[index];
|
|
|
|
@@ -4570,7 +4570,7 @@ class HttpManager {
|
|
|
|
// for more information see: https://github.com/actions/http-client/blob/04e5ad73cd3fd1f5610a32116b0759eddf6570d2/index.ts#L292
|
|
|
|
// for more information see: https://github.com/actions/http-client/blob/04e5ad73cd3fd1f5610a32116b0759eddf6570d2/index.ts#L292
|
|
|
|
disposeAndReplaceClient(index) {
|
|
|
|
disposeAndReplaceClient(index) {
|
|
|
|
this.clients[index].dispose();
|
|
|
|
this.clients[index].dispose();
|
|
|
|
this.clients[index] = utils_1.createHttpClient();
|
|
|
|
this.clients[index] = utils_1.createHttpClient(this.userAgent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
disposeAndReplaceAllClients() {
|
|
|
|
disposeAndReplaceAllClients() {
|
|
|
|
for (const [index] of this.clients.entries()) {
|
|
|
|
for (const [index] of this.clients.entries()) {
|
|
|
|
@@ -5929,7 +5929,7 @@ const upload_gzip_1 = __webpack_require__(647);
|
|
|
|
const stat = util_1.promisify(fs.stat);
|
|
|
|
const stat = util_1.promisify(fs.stat);
|
|
|
|
class UploadHttpClient {
|
|
|
|
class UploadHttpClient {
|
|
|
|
constructor() {
|
|
|
|
constructor() {
|
|
|
|
this.uploadHttpManager = new http_manager_1.HttpManager(config_variables_1.getUploadFileConcurrency());
|
|
|
|
this.uploadHttpManager = new http_manager_1.HttpManager(config_variables_1.getUploadFileConcurrency(), '@actions/artifact-upload');
|
|
|
|
this.statusReporter = new status_reporter_1.StatusReporter(10000);
|
|
|
|
this.statusReporter = new status_reporter_1.StatusReporter(10000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@@ -5947,8 +5947,8 @@ class UploadHttpClient {
|
|
|
|
const artifactUrl = utils_1.getArtifactUrl();
|
|
|
|
const artifactUrl = utils_1.getArtifactUrl();
|
|
|
|
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
|
|
|
// 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 client = this.uploadHttpManager.getClient(0);
|
|
|
|
const requestOptions = utils_1.getUploadRequestOptions('application/json', false);
|
|
|
|
const headers = utils_1.getUploadHeaders('application/json', false);
|
|
|
|
const rawResponse = yield client.post(artifactUrl, data, requestOptions);
|
|
|
|
const rawResponse = yield client.post(artifactUrl, data, headers);
|
|
|
|
const body = yield rawResponse.readBody();
|
|
|
|
const body = yield rawResponse.readBody();
|
|
|
|
if (utils_1.isSuccessStatusCode(rawResponse.message.statusCode) && body) {
|
|
|
|
if (utils_1.isSuccessStatusCode(rawResponse.message.statusCode) && body) {
|
|
|
|
return JSON.parse(body);
|
|
|
|
return JSON.parse(body);
|
|
|
|
@@ -6060,21 +6060,25 @@ class UploadHttpClient {
|
|
|
|
// for creating a new GZip file, an in-memory buffer is used for compression
|
|
|
|
// for creating a new GZip file, an in-memory buffer is used for compression
|
|
|
|
if (totalFileSize < 65536) {
|
|
|
|
if (totalFileSize < 65536) {
|
|
|
|
const buffer = yield upload_gzip_1.createGZipFileInBuffer(parameters.file);
|
|
|
|
const buffer = yield upload_gzip_1.createGZipFileInBuffer(parameters.file);
|
|
|
|
let uploadStream;
|
|
|
|
//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) {
|
|
|
|
if (totalFileSize < buffer.byteLength) {
|
|
|
|
// compression did not help with reducing the size, use a readable stream from the original file for upload
|
|
|
|
// compression did not help with reducing the size, use a readable stream from the original file for upload
|
|
|
|
uploadStream = fs.createReadStream(parameters.file);
|
|
|
|
openUploadStream = () => fs.createReadStream(parameters.file);
|
|
|
|
isGzip = false;
|
|
|
|
isGzip = false;
|
|
|
|
uploadFileSize = totalFileSize;
|
|
|
|
uploadFileSize = totalFileSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
// create a readable stream using a PassThrough stream that is both readable and writable
|
|
|
|
// create a readable stream using a PassThrough stream that is both readable and writable
|
|
|
|
const passThrough = new stream.PassThrough();
|
|
|
|
openUploadStream = () => {
|
|
|
|
passThrough.end(buffer);
|
|
|
|
const passThrough = new stream.PassThrough();
|
|
|
|
uploadStream = passThrough;
|
|
|
|
passThrough.end(buffer);
|
|
|
|
|
|
|
|
return passThrough;
|
|
|
|
|
|
|
|
};
|
|
|
|
uploadFileSize = buffer.byteLength;
|
|
|
|
uploadFileSize = buffer.byteLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, uploadStream, 0, uploadFileSize - 1, uploadFileSize, isGzip, totalFileSize);
|
|
|
|
const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, openUploadStream, 0, uploadFileSize - 1, uploadFileSize, isGzip, totalFileSize);
|
|
|
|
if (!result) {
|
|
|
|
if (!result) {
|
|
|
|
// chunk failed to upload
|
|
|
|
// chunk failed to upload
|
|
|
|
isUploadSuccessful = false;
|
|
|
|
isUploadSuccessful = false;
|
|
|
|
@@ -6116,7 +6120,7 @@ class UploadHttpClient {
|
|
|
|
failedChunkSizes += chunkSize;
|
|
|
|
failedChunkSizes += chunkSize;
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, fs.createReadStream(uploadFilePath, {
|
|
|
|
const result = yield this.uploadChunk(httpClientIndex, parameters.resourceUrl, () => fs.createReadStream(uploadFilePath, {
|
|
|
|
start,
|
|
|
|
start,
|
|
|
|
end,
|
|
|
|
end,
|
|
|
|
autoClose: false
|
|
|
|
autoClose: false
|
|
|
|
@@ -6146,7 +6150,7 @@ class UploadHttpClient {
|
|
|
|
* indicates a retryable status, we try to upload the chunk as well
|
|
|
|
* 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 {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 {string} resourceUrl Url of the resource that the chunk will be uploaded to
|
|
|
|
* @param {NodeJS.ReadableStream} data Stream of the file that will be uploaded
|
|
|
|
* @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} 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} 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 {number} uploadFileSize Total size of the file in bytes that is being uploaded
|
|
|
|
@@ -6154,13 +6158,13 @@ class UploadHttpClient {
|
|
|
|
* @param {number} totalFileSize Original total size of the file that is being uploaded
|
|
|
|
* @param {number} totalFileSize Original total size of the file that is being uploaded
|
|
|
|
* @returns if the chunk was successfully uploaded
|
|
|
|
* @returns if the chunk was successfully uploaded
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
uploadChunk(httpClientIndex, resourceUrl, data, start, end, uploadFileSize, isGzip, totalFileSize) {
|
|
|
|
uploadChunk(httpClientIndex, resourceUrl, openStream, start, end, uploadFileSize, isGzip, totalFileSize) {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
// prepare all the necessary headers before making any http call
|
|
|
|
// prepare all the necessary headers before making any http call
|
|
|
|
const requestOptions = utils_1.getUploadRequestOptions('application/octet-stream', true, isGzip, totalFileSize, end - start + 1, utils_1.getContentRange(start, end, uploadFileSize));
|
|
|
|
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 uploadChunkRequest = () => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const client = this.uploadHttpManager.getClient(httpClientIndex);
|
|
|
|
const client = this.uploadHttpManager.getClient(httpClientIndex);
|
|
|
|
return yield client.sendStream('PUT', resourceUrl, data, requestOptions);
|
|
|
|
return yield client.sendStream('PUT', resourceUrl, openStream(), headers);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
let retryCount = 0;
|
|
|
|
let retryCount = 0;
|
|
|
|
const retryLimit = config_variables_1.getRetryLimit();
|
|
|
|
const retryLimit = config_variables_1.getRetryLimit();
|
|
|
|
@@ -6238,7 +6242,7 @@ class UploadHttpClient {
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
patchArtifactSize(size, artifactName) {
|
|
|
|
patchArtifactSize(size, artifactName) {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const requestOptions = utils_1.getUploadRequestOptions('application/json', false);
|
|
|
|
const headers = utils_1.getUploadHeaders('application/json', false);
|
|
|
|
const resourceUrl = new url_1.URL(utils_1.getArtifactUrl());
|
|
|
|
const resourceUrl = new url_1.URL(utils_1.getArtifactUrl());
|
|
|
|
resourceUrl.searchParams.append('artifactName', artifactName);
|
|
|
|
resourceUrl.searchParams.append('artifactName', artifactName);
|
|
|
|
const parameters = { Size: size };
|
|
|
|
const parameters = { Size: size };
|
|
|
|
@@ -6246,7 +6250,7 @@ class UploadHttpClient {
|
|
|
|
core.debug(`URL is ${resourceUrl.toString()}`);
|
|
|
|
core.debug(`URL is ${resourceUrl.toString()}`);
|
|
|
|
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
|
|
|
// 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 client = this.uploadHttpManager.getClient(0);
|
|
|
|
const response = yield client.patch(resourceUrl.toString(), data, requestOptions);
|
|
|
|
const response = yield client.patch(resourceUrl.toString(), data, headers);
|
|
|
|
const body = yield response.readBody();
|
|
|
|
const body = yield response.readBody();
|
|
|
|
if (utils_1.isSuccessStatusCode(response.message.statusCode)) {
|
|
|
|
if (utils_1.isSuccessStatusCode(response.message.statusCode)) {
|
|
|
|
core.debug(`Artifact ${artifactName} has been successfully uploaded, total size in bytes: ${size}`);
|
|
|
|
core.debug(`Artifact ${artifactName} has been successfully uploaded, total size in bytes: ${size}`);
|
|
|
|
@@ -6634,6 +6638,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
|
const core = __importStar(__webpack_require__(470));
|
|
|
|
const core = __importStar(__webpack_require__(470));
|
|
|
|
const artifact = __importStar(__webpack_require__(214));
|
|
|
|
const artifact = __importStar(__webpack_require__(214));
|
|
|
|
|
|
|
|
const os = __importStar(__webpack_require__(87));
|
|
|
|
const path_1 = __webpack_require__(622);
|
|
|
|
const path_1 = __webpack_require__(622);
|
|
|
|
const constants_1 = __webpack_require__(694);
|
|
|
|
const constants_1 = __webpack_require__(694);
|
|
|
|
function run() {
|
|
|
|
function run() {
|
|
|
|
@@ -6641,12 +6646,21 @@ function run() {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const name = core.getInput(constants_1.Inputs.Name, { required: false });
|
|
|
|
const name = core.getInput(constants_1.Inputs.Name, { required: false });
|
|
|
|
const path = core.getInput(constants_1.Inputs.Path, { required: false });
|
|
|
|
const path = core.getInput(constants_1.Inputs.Path, { required: false });
|
|
|
|
|
|
|
|
let resolvedPath;
|
|
|
|
|
|
|
|
// resolve tilde expansions, path.replace only replaces the first occurrence of a pattern
|
|
|
|
|
|
|
|
if (path.startsWith(`~`)) {
|
|
|
|
|
|
|
|
resolvedPath = path_1.resolve(path.replace('~', os.homedir()));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
resolvedPath = path_1.resolve(path);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
core.debug(`Resolved path is ${resolvedPath}`);
|
|
|
|
const artifactClient = artifact.create();
|
|
|
|
const artifactClient = artifact.create();
|
|
|
|
if (!name) {
|
|
|
|
if (!name) {
|
|
|
|
// download all artifacts
|
|
|
|
// download all artifacts
|
|
|
|
core.info('No artifact name specified, downloading all artifacts');
|
|
|
|
core.info('No artifact name specified, downloading all artifacts');
|
|
|
|
core.info('Creating an extra directory for each artifact that is being downloaded');
|
|
|
|
core.info('Creating an extra directory for each artifact that is being downloaded');
|
|
|
|
const downloadResponse = yield artifactClient.downloadAllArtifacts(path);
|
|
|
|
const downloadResponse = yield artifactClient.downloadAllArtifacts(resolvedPath);
|
|
|
|
core.info(`There were ${downloadResponse.length} artifacts downloaded`);
|
|
|
|
core.info(`There were ${downloadResponse.length} artifacts downloaded`);
|
|
|
|
for (const artifact of downloadResponse) {
|
|
|
|
for (const artifact of downloadResponse) {
|
|
|
|
core.info(`Artifact ${artifact.artifactName} was downloaded to ${artifact.downloadPath}`);
|
|
|
|
core.info(`Artifact ${artifact.artifactName} was downloaded to ${artifact.downloadPath}`);
|
|
|
|
@@ -6658,12 +6672,12 @@ function run() {
|
|
|
|
const downloadOptions = {
|
|
|
|
const downloadOptions = {
|
|
|
|
createArtifactFolder: false
|
|
|
|
createArtifactFolder: false
|
|
|
|
};
|
|
|
|
};
|
|
|
|
const downloadResponse = yield artifactClient.downloadArtifact(name, path, downloadOptions);
|
|
|
|
const downloadResponse = yield artifactClient.downloadArtifact(name, resolvedPath, downloadOptions);
|
|
|
|
core.info(`Artifact ${downloadResponse.artifactName} was downloaded to ${downloadResponse.downloadPath}`);
|
|
|
|
core.info(`Artifact ${downloadResponse.artifactName} was downloaded to ${downloadResponse.downloadPath}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// output the directory that the artifact(s) was/were downloaded to
|
|
|
|
// output the directory that the artifact(s) was/were downloaded to
|
|
|
|
// if no path is provided, an empty string resolves to the current working directory
|
|
|
|
// if no path is provided, an empty string resolves to the current working directory
|
|
|
|
core.setOutput(constants_1.Outputs.DownloadPath, path_1.resolve(path));
|
|
|
|
core.setOutput(constants_1.Outputs.DownloadPath, resolvedPath);
|
|
|
|
core.info('Artifact download has finished successfully');
|
|
|
|
core.info('Artifact download has finished successfully');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
catch (err) {
|
|
|
|
@@ -6716,7 +6730,7 @@ const http_manager_1 = __webpack_require__(452);
|
|
|
|
const config_variables_1 = __webpack_require__(401);
|
|
|
|
const config_variables_1 = __webpack_require__(401);
|
|
|
|
class DownloadHttpClient {
|
|
|
|
class DownloadHttpClient {
|
|
|
|
constructor() {
|
|
|
|
constructor() {
|
|
|
|
this.downloadHttpManager = new http_manager_1.HttpManager(config_variables_1.getDownloadFileConcurrency());
|
|
|
|
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
|
|
|
|
// downloads are usually significantly faster than uploads so display status information every second
|
|
|
|
this.statusReporter = new status_reporter_1.StatusReporter(1000);
|
|
|
|
this.statusReporter = new status_reporter_1.StatusReporter(1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -6728,8 +6742,8 @@ class DownloadHttpClient {
|
|
|
|
const artifactUrl = utils_1.getArtifactUrl();
|
|
|
|
const artifactUrl = utils_1.getArtifactUrl();
|
|
|
|
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
|
|
|
// 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 client = this.downloadHttpManager.getClient(0);
|
|
|
|
const requestOptions = utils_1.getDownloadRequestOptions('application/json');
|
|
|
|
const headers = utils_1.getDownloadHeaders('application/json');
|
|
|
|
const response = yield client.get(artifactUrl, requestOptions);
|
|
|
|
const response = yield client.get(artifactUrl, headers);
|
|
|
|
const body = yield response.readBody();
|
|
|
|
const body = yield response.readBody();
|
|
|
|
if (utils_1.isSuccessStatusCode(response.message.statusCode) && body) {
|
|
|
|
if (utils_1.isSuccessStatusCode(response.message.statusCode) && body) {
|
|
|
|
return JSON.parse(body);
|
|
|
|
return JSON.parse(body);
|
|
|
|
@@ -6750,8 +6764,8 @@ class DownloadHttpClient {
|
|
|
|
resourceUrl.searchParams.append('itemPath', artifactName);
|
|
|
|
resourceUrl.searchParams.append('itemPath', artifactName);
|
|
|
|
// use the first client from the httpManager, `keep-alive` is not used so the connection will close immediately
|
|
|
|
// 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 client = this.downloadHttpManager.getClient(0);
|
|
|
|
const requestOptions = utils_1.getDownloadRequestOptions('application/json');
|
|
|
|
const headers = utils_1.getDownloadHeaders('application/json');
|
|
|
|
const response = yield client.get(resourceUrl.toString(), requestOptions);
|
|
|
|
const response = yield client.get(resourceUrl.toString(), headers);
|
|
|
|
const body = yield response.readBody();
|
|
|
|
const body = yield response.readBody();
|
|
|
|
if (utils_1.isSuccessStatusCode(response.message.statusCode) && body) {
|
|
|
|
if (utils_1.isSuccessStatusCode(response.message.statusCode) && body) {
|
|
|
|
return JSON.parse(body);
|
|
|
|
return JSON.parse(body);
|
|
|
|
@@ -6808,15 +6822,16 @@ class DownloadHttpClient {
|
|
|
|
let retryCount = 0;
|
|
|
|
let retryCount = 0;
|
|
|
|
const retryLimit = config_variables_1.getRetryLimit();
|
|
|
|
const retryLimit = config_variables_1.getRetryLimit();
|
|
|
|
const destinationStream = fs.createWriteStream(downloadPath);
|
|
|
|
const destinationStream = fs.createWriteStream(downloadPath);
|
|
|
|
const requestOptions = utils_1.getDownloadRequestOptions('application/json', true, true);
|
|
|
|
const headers = utils_1.getDownloadHeaders('application/json', true, true);
|
|
|
|
// a single GET request is used to download a file
|
|
|
|
// a single GET request is used to download a file
|
|
|
|
const makeDownloadRequest = () => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const makeDownloadRequest = () => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
const client = this.downloadHttpManager.getClient(httpClientIndex);
|
|
|
|
const client = this.downloadHttpManager.getClient(httpClientIndex);
|
|
|
|
return yield client.get(artifactLocation, requestOptions);
|
|
|
|
return yield client.get(artifactLocation, headers);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
// check the response headers to determine if the file was compressed using gzip
|
|
|
|
// check the response headers to determine if the file was compressed using gzip
|
|
|
|
const isGzip = (headers) => {
|
|
|
|
const isGzip = (incomingHeaders) => {
|
|
|
|
return ('content-encoding' in headers && headers['content-encoding'] === 'gzip');
|
|
|
|
return ('content-encoding' in incomingHeaders &&
|
|
|
|
|
|
|
|
incomingHeaders['content-encoding'] === 'gzip');
|
|
|
|
};
|
|
|
|
};
|
|
|
|
// Increments the current retry count and then checks if the retry limit has been reached
|
|
|
|
// 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,
|
|
|
|
// If there have been too many retries, fail so the download stops. If there is a retryAfterValue value provided,
|
|
|
|
@@ -7245,7 +7260,8 @@ function isRetryableStatusCode(statusCode) {
|
|
|
|
http_client_1.HttpCodes.BadGateway,
|
|
|
|
http_client_1.HttpCodes.BadGateway,
|
|
|
|
http_client_1.HttpCodes.ServiceUnavailable,
|
|
|
|
http_client_1.HttpCodes.ServiceUnavailable,
|
|
|
|
http_client_1.HttpCodes.GatewayTimeout,
|
|
|
|
http_client_1.HttpCodes.GatewayTimeout,
|
|
|
|
http_client_1.HttpCodes.TooManyRequests
|
|
|
|
http_client_1.HttpCodes.TooManyRequests,
|
|
|
|
|
|
|
|
413 // Payload Too Large
|
|
|
|
];
|
|
|
|
];
|
|
|
|
return retryableStatusCodes.includes(statusCode);
|
|
|
|
return retryableStatusCodes.includes(statusCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -7292,9 +7308,9 @@ exports.getContentRange = getContentRange;
|
|
|
|
* @param {boolean} isKeepAlive is the same connection being used to make multiple calls
|
|
|
|
* @param {boolean} isKeepAlive is the same connection being used to make multiple calls
|
|
|
|
* @param {boolean} acceptGzip can we accept a gzip encoded response
|
|
|
|
* @param {boolean} acceptGzip can we accept a gzip encoded response
|
|
|
|
* @param {string} acceptType the type of content that we can accept
|
|
|
|
* @param {string} acceptType the type of content that we can accept
|
|
|
|
* @returns appropriate request options to make a specific http call during artifact download
|
|
|
|
* @returns appropriate headers to make a specific http call during artifact download
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function getDownloadRequestOptions(contentType, isKeepAlive, acceptGzip) {
|
|
|
|
function getDownloadHeaders(contentType, isKeepAlive, acceptGzip) {
|
|
|
|
const requestOptions = {};
|
|
|
|
const requestOptions = {};
|
|
|
|
if (contentType) {
|
|
|
|
if (contentType) {
|
|
|
|
requestOptions['Content-Type'] = contentType;
|
|
|
|
requestOptions['Content-Type'] = contentType;
|
|
|
|
@@ -7315,7 +7331,7 @@ function getDownloadRequestOptions(contentType, isKeepAlive, acceptGzip) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return requestOptions;
|
|
|
|
return requestOptions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exports.getDownloadRequestOptions = getDownloadRequestOptions;
|
|
|
|
exports.getDownloadHeaders = getDownloadHeaders;
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Sets all the necessary headers when uploading an artifact
|
|
|
|
* Sets all the necessary headers when uploading an artifact
|
|
|
|
* @param {string} contentType the type of content being uploaded
|
|
|
|
* @param {string} contentType the type of content being uploaded
|
|
|
|
@@ -7324,9 +7340,9 @@ exports.getDownloadRequestOptions = getDownloadRequestOptions;
|
|
|
|
* @param {number} uncompressedLength the original size of the content if something is being uploaded that has been compressed
|
|
|
|
* @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 {number} contentLength the length of the content that is being uploaded
|
|
|
|
* @param {string} contentRange the range of the content that is being uploaded
|
|
|
|
* @param {string} contentRange the range of the content that is being uploaded
|
|
|
|
* @returns appropriate request options to make a specific http call during artifact upload
|
|
|
|
* @returns appropriate headers to make a specific http call during artifact upload
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
function getUploadRequestOptions(contentType, isKeepAlive, isGzip, uncompressedLength, contentLength, contentRange) {
|
|
|
|
function getUploadHeaders(contentType, isKeepAlive, isGzip, uncompressedLength, contentLength, contentRange) {
|
|
|
|
const requestOptions = {};
|
|
|
|
const requestOptions = {};
|
|
|
|
requestOptions['Accept'] = `application/json;api-version=${getApiVersion()}`;
|
|
|
|
requestOptions['Accept'] = `application/json;api-version=${getApiVersion()}`;
|
|
|
|
if (contentType) {
|
|
|
|
if (contentType) {
|
|
|
|
@@ -7349,9 +7365,9 @@ function getUploadRequestOptions(contentType, isKeepAlive, isGzip, uncompressedL
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return requestOptions;
|
|
|
|
return requestOptions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
exports.getUploadRequestOptions = getUploadRequestOptions;
|
|
|
|
exports.getUploadHeaders = getUploadHeaders;
|
|
|
|
function createHttpClient() {
|
|
|
|
function createHttpClient(userAgent) {
|
|
|
|
return new http_client_1.HttpClient('action/artifact', [
|
|
|
|
return new http_client_1.HttpClient(userAgent, [
|
|
|
|
new auth_1.BearerCredentialHandler(config_variables_1.getRuntimeToken())
|
|
|
|
new auth_1.BearerCredentialHandler(config_variables_1.getRuntimeToken())
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|