diff --git a/.github/workflows/check-dist.yaml b/.github/workflows/check-dist.yaml new file mode 100644 index 0000000..288c7df --- /dev/null +++ b/.github/workflows/check-dist.yaml @@ -0,0 +1,38 @@ +name: Check dist + +on: + push: + branches: + - main + paths-ignore: + - "**.md" + pull_request: + paths-ignore: + - "**.md" + workflow_dispatch: + +jobs: + check-dist: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4.1.6 + + - name: Set Node.js 20.14.x + uses: actions/setup-node@v4 + with: + node-version: 20.14.x + + - name: Install dependencies + run: npm ci + + - name: Rebuild the index.js file + run: npm run build + + - name: Compare the expected and actual dist/ directories + run: | + if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then + echo "Detected uncommitted changes after build. See status below:" + git diff + exit 1 + fi diff --git a/.github/workflows/commitlint.yaml b/.github/workflows/commitlint.yaml new file mode 100644 index 0000000..5038e93 --- /dev/null +++ b/.github/workflows/commitlint.yaml @@ -0,0 +1,13 @@ +name: Lint Commit Messages +on: [pull_request] + +permissions: + contents: read + pull-requests: read + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: wagoid/commitlint-github-action@v6 diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml new file mode 100644 index 0000000..a2731ad --- /dev/null +++ b/.github/workflows/release-please.yaml @@ -0,0 +1,22 @@ +on: + push: + branches: + - "main" +name: release-please +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - name: Extract branch name + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: extract_branch + - uses: google-github-actions/release-please-action@v3 + with: + token: ${{ secrets.PAT }} + pull-request-title-pattern: "chore: release ${version}" + release-type: node + package-name: rudder-transformation-action + default-branch: ${{ steps.extract_branch.outputs.branch }} + changelog-types: '[{"type":"feat","section":"Features","hidden":false},{"type":"fix","section":"Bug Fixes","hidden":false},{"type":"chore","section":"Miscellaneous","hidden":false},{"type":"refactor","section":"Miscellaneous","hidden":false},{"type":"test","section":"Miscellaneous","hidden":false},{"type":"doc","section":"Documentation","hidden":false}]' + bump-minor-pre-major: true diff --git a/.github/workflows/semantic-pr.yaml b/.github/workflows/semantic-pr.yaml new file mode 100644 index 0000000..ae8ea23 --- /dev/null +++ b/.github/workflows/semantic-pr.yaml @@ -0,0 +1,49 @@ +name: "Semantic pull requests" + +on: pull_request + +jobs: + main: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + fix + feat + chore + refactor + exp + doc + test + requireScope: false + subjectPattern: ^(?![A-Z]).+$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + doesn't start with an uppercase character. + # For work-in-progress PRs you can typically use draft pull requests + # from GitHub. However, private repositories on the free plan don't have + # this option and therefore this action allows you to opt-in to using the + # special "[WIP]" prefix to indicate this state. This will avoid the + # validation of the PR title and the pull request checks remain pending. + # Note that a second check will be reported if this is enabled. + wip: true + # When using "Squash and merge" on a PR with only one commit, GitHub + # will suggest using that commit message instead of the PR title for the + # merge commit, and it's easy to commit this by mistake. Enable this option + # to also validate the commit message for one commit PRs. + validateSingleCommit: true + # Related to `validateSingleCommit` you can opt-in to validate that the PR + # title matches a single commit to avoid confusion. + validateSingleCommitMatchesPrTitle: true + # If the PR contains one of these labels, the validation is skipped. + # Multiple labels can be separated by newlines. + # If you want to rerun the validation when labels change, you might want + # to use the `labeled` and `unlabeled` event triggers in your workflow. + ignoreLabels: | + bot + dependencies diff --git a/.gitignore b/.gitignore index 9a30b15..5d4ef0c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules/ package-lock.json -.env \ No newline at end of file +.env +coverage/ +test-outputs/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69de29 diff --git a/action.yml b/action.yml index 0ffda73..6079b72 100644 --- a/action.yml +++ b/action.yml @@ -1,25 +1,25 @@ -name: 'Rudder Transformation Action' -description: 'Tests transformations and libraries from your repo and publishes them to your Rudderstack workspace' +name: "Rudder Transformation Action" +description: "Tests transformations and libraries from your repo and publishes them to your Rudderstack workspace" branding: - icon: activity - color: purple + icon: activity + color: purple inputs: - metaPath: - description: 'File containing metadata about transformation and libraries' - required: true - email: - description: 'Owner email of the workspace' - required: true - accessToken: - description: 'accessToken generated for a workspace' - required: true - serverEndpoint: - description: 'backend url' - required: false - default: 'https://api.rudderstack.com' - uploadTestArtifact: - description: 'Toggle for enabling artifacts' - required: false + metaPath: + description: "File containing metadata about transformation and libraries" + required: true + email: + description: "Owner email of the workspace" + required: true + accessToken: + description: "accessToken generated for a workspace" + required: true + serverEndpoint: + description: "backend url" + required: false + default: "https://api.rudderstack.com" + uploadTestArtifact: + description: "Toggle for enabling artifacts" + required: false runs: - using: 'node12' - main: 'dist/index.js' + using: "node20" + main: "dist/index.js" diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..69bc4c8 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,10 @@ +module.exports = { + extends: ["@commitlint/config-conventional"], + rules: { + "type-enum": () => [ + 2, + "always", + ["fix", "feat", "chore", "refactor", "docs", "test"], + ], + }, +}; diff --git a/dist/index.js b/dist/index.js index f2b9a33..2721045 100644 --- a/dist/index.js +++ b/dist/index.js @@ -27,7 +27,11 @@ exports.create = create; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -40,7 +44,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -78,9 +82,9 @@ class DefaultArtifactClient { return __awaiter(this, void 0, void 0, function* () { core.info(`Starting artifact upload For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging`); - path_and_artifact_name_validation_1.checkArtifactName(name); + (0, path_and_artifact_name_validation_1.checkArtifactName)(name); // Get specification for the files being uploaded - const uploadSpecification = upload_specification_1.getUploadSpecification(name, rootDirectory, files); + const uploadSpecification = (0, upload_specification_1.getUploadSpecification)(name, rootDirectory, files); const uploadResponse = { artifactName: name, artifactItems: [], @@ -139,20 +143,20 @@ Note: The size of downloaded zips can differ significantly from the reported siz } const items = yield downloadHttpClient.getContainerItems(artifactToDownload.name, artifactToDownload.fileContainerResourceUrl); if (!path) { - path = config_variables_1.getWorkSpaceDirectory(); + path = (0, config_variables_1.getWorkSpaceDirectory)(); } - path = path_1.normalize(path); - path = path_1.resolve(path); + path = (0, path_1.normalize)(path); + path = (0, 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); + const downloadSpecification = (0, 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 (0, utils_1.createDirectoriesForArtifact)(downloadSpecification.directoryStructure); + core.info('Directory structure has been set up for the artifact'); + yield (0, utils_1.createEmptyFilesForArtifact)(downloadSpecification.emptyFilesToCreate); yield downloadHttpClient.downloadSingleArtifact(downloadSpecification.filesToDownload); } return { @@ -171,10 +175,10 @@ Note: The size of downloaded zips can differ significantly from the reported siz return response; } if (!path) { - path = config_variables_1.getWorkSpaceDirectory(); + path = (0, config_variables_1.getWorkSpaceDirectory)(); } - path = path_1.normalize(path); - path = path_1.resolve(path); + path = (0, path_1.normalize)(path); + path = (0, path_1.resolve)(path); let downloadedArtifacts = 0; while (downloadedArtifacts < artifacts.count) { const currentArtifactToDownload = artifacts.value[downloadedArtifacts]; @@ -182,13 +186,13 @@ Note: The size of downloaded zips can differ significantly from the reported siz core.info(`starting download of artifact ${currentArtifactToDownload.name} : ${downloadedArtifacts}/${artifacts.count}`); // 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); + const downloadSpecification = (0, 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 (0, utils_1.createDirectoriesForArtifact)(downloadSpecification.directoryStructure); + yield (0, utils_1.createEmptyFilesForArtifact)(downloadSpecification.emptyFilesToCreate); yield downloadHttpClient.downloadSingleArtifact(downloadSpecification.filesToDownload); } response.push({ @@ -211,7 +215,7 @@ exports.DefaultArtifactClient = DefaultArtifactClient; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getRetentionDays = exports.getWorkSpaceDirectory = exports.getWorkFlowRunId = exports.getRuntimeUrl = exports.getRuntimeToken = exports.getDownloadFileConcurrency = exports.getInitialRetryIntervalInMilliseconds = exports.getRetryMultiplier = exports.getRetryLimit = exports.getUploadChunkSize = exports.getUploadFileConcurrency = void 0; +exports.isGhes = exports.getRetentionDays = exports.getWorkSpaceDirectory = exports.getWorkFlowRunId = exports.getRuntimeUrl = exports.getRuntimeToken = exports.getDownloadFileConcurrency = exports.getInitialRetryIntervalInMilliseconds = exports.getRetryMultiplier = exports.getRetryLimit = exports.getUploadChunkSize = exports.getUploadFileConcurrency = void 0; // The number of concurrent uploads that happens at the same time function getUploadFileConcurrency() { return 2; @@ -280,6 +284,11 @@ function getRetentionDays() { return process.env['GITHUB_RETENTION_DAYS']; } exports.getRetentionDays = getRetentionDays; +function isGhes() { + const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com'); + return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'; +} +exports.isGhes = isGhes; //# sourceMappingURL=config-variables.js.map /***/ }), @@ -601,7 +610,11 @@ exports["default"] = CRC64; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -614,7 +627,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -641,7 +654,7 @@ const config_variables_1 = __nccwpck_require__(2222); const requestUtils_1 = __nccwpck_require__(755); class DownloadHttpClient { constructor() { - this.downloadHttpManager = new http_manager_1.HttpManager(config_variables_1.getDownloadFileConcurrency(), '@actions/artifact-download'); + this.downloadHttpManager = new http_manager_1.HttpManager((0, 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); } @@ -650,11 +663,11 @@ class DownloadHttpClient { */ listArtifacts() { return __awaiter(this, void 0, void 0, function* () { - const artifactUrl = utils_1.getArtifactUrl(); + const artifactUrl = (0, 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 headers = (0, utils_1.getDownloadHeaders)('application/json'); + const response = yield (0, 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); }); @@ -671,8 +684,8 @@ class DownloadHttpClient { 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 headers = (0, utils_1.getDownloadHeaders)('application/json'); + const response = yield (0, 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); }); @@ -683,7 +696,7 @@ class DownloadHttpClient { */ downloadSingleArtifact(downloadItems) { return __awaiter(this, void 0, void 0, function* () { - const DOWNLOAD_CONCURRENCY = config_variables_1.getDownloadFileConcurrency(); + const DOWNLOAD_CONCURRENCY = (0, 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()]; @@ -723,9 +736,9 @@ class DownloadHttpClient { downloadIndividualFile(httpClientIndex, artifactLocation, downloadPath) { return __awaiter(this, void 0, void 0, function* () { let retryCount = 0; - const retryLimit = config_variables_1.getRetryLimit(); + const retryLimit = (0, config_variables_1.getRetryLimit)(); let destinationStream = fs.createWriteStream(downloadPath); - const headers = utils_1.getDownloadHeaders('application/json', true, true); + const headers = (0, 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); @@ -749,13 +762,13 @@ class DownloadHttpClient { 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); + yield (0, utils_1.sleep)(retryAfterValue); } else { // Back off using an exponential value that depends on the retry count - const backoffTime = utils_1.getExponentialRetryTimeInMilliseconds(retryCount); + const backoffTime = (0, utils_1.getExponentialRetryTimeInMilliseconds)(retryCount); core.info(`Exponential backoff for retry #${retryCount}. Waiting for ${backoffTime} milliseconds before continuing the download`); - yield utils_1.sleep(backoffTime); + yield (0, utils_1.sleep)(backoffTime); } core.info(`Finished backoff for retry #${retryCount}, continuing with download`); } @@ -779,7 +792,7 @@ class DownloadHttpClient { resolve(); } }); - yield utils_1.rmFile(fileDownloadPath); + yield (0, utils_1.rmFile)(fileDownloadPath); destinationStream = fs.createWriteStream(fileDownloadPath); }); // keep trying to download a file until a retry limit has been reached @@ -798,7 +811,7 @@ class DownloadHttpClient { continue; } let forceRetry = false; - if (utils_1.isSuccessStatusCode(response.message.statusCode)) { + if ((0, 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 @@ -806,7 +819,7 @@ class DownloadHttpClient { 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))) { + isAllBytesReceived(response.message.headers['content-length'], yield (0, utils_1.getFileSize)(downloadPath))) { return; } else { @@ -818,17 +831,17 @@ class DownloadHttpClient { forceRetry = true; } } - if (forceRetry || utils_1.isRetryableStatusCode(response.message.statusCode)) { + if (forceRetry || (0, 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)) + (0, utils_1.isThrottledStatusCode)(response.message.statusCode) + ? yield backOff((0, utils_1.tryGetRetryAfterValueTimeInMilliseconds)(response.message.headers)) : yield backOff(); } else { // Some unexpected response code, fail immediately and stop the download - utils_1.displayHttpDiagnostics(response); + (0, utils_1.displayHttpDiagnostics)(response); return Promise.reject(new Error(`Unexpected http ${response.message.statusCode} during download for ${artifactLocation}`)); } } @@ -847,14 +860,14 @@ class DownloadHttpClient { const gunzip = zlib.createGunzip(); response.message .on('error', error => { - core.error(`An error occurred while attempting to read the response stream`); + core.info(`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`); + core.info(`An error occurred while attempting to decompress the response stream`); destinationStream.close(); reject(error); }) @@ -863,14 +876,14 @@ class DownloadHttpClient { resolve(); }) .on('error', error => { - core.error(`An error occurred while writing a downloaded file to ${destinationStream.path}`); + core.info(`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`); + core.info(`An error occurred while attempting to read the response stream`); destinationStream.close(); reject(error); }) @@ -879,7 +892,7 @@ class DownloadHttpClient { resolve(); }) .on('error', error => { - core.error(`An error occurred while writing a downloaded file to ${destinationStream.path}`); + core.info(`An error occurred while writing a downloaded file to ${destinationStream.path}`); reject(error); }); } @@ -900,7 +913,11 @@ exports.DownloadHttpClient = DownloadHttpClient; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -913,7 +930,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -991,7 +1008,7 @@ class HttpManager { throw new Error('There must be at least one client'); } this.userAgent = userAgent; - this.clients = new Array(clientCount).fill(utils_1.createHttpClient(userAgent)); + this.clients = new Array(clientCount).fill((0, utils_1.createHttpClient)(userAgent)); } getClient(index) { return this.clients[index]; @@ -1000,7 +1017,7 @@ class HttpManager { // 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); + this.clients[index] = (0, utils_1.createHttpClient)(this.userAgent); } disposeAndReplaceAllClients() { for (const [index] of this.clients.entries()) { @@ -1061,7 +1078,7 @@ Invalid characters include: ${Array.from(invalidArtifactNameCharacters.values()) These characters are not allowed in the artifact name due to limitations with certain file systems such as NTFS. To maintain file system agnostic behavior, these characters are intentionally not allowed to prevent potential problems with downloads on different file systems.`); } } - core_1.info(`Artifact name is valid!`); + (0, core_1.info)(`Artifact name is valid!`); } exports.checkArtifactName = checkArtifactName; /** @@ -1094,7 +1111,11 @@ exports.checkArtifactFilePath = checkArtifactFilePath; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -1107,7 +1128,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -1137,14 +1158,14 @@ function retry(name, operation, customErrorMessages, maxAttempts) { try { response = yield operation(); statusCode = response.message.statusCode; - if (utils_1.isSuccessStatusCode(statusCode)) { + if ((0, 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); + isRetryable = (0, utils_1.isRetryableStatusCode)(statusCode); errorMessage = `Artifact service responded with ${statusCode}`; } catch (error) { @@ -1154,16 +1175,16 @@ function retry(name, operation, customErrorMessages, maxAttempts) { if (!isRetryable) { core.info(`${name} - Error is not retryable`); if (response) { - utils_1.displayHttpDiagnostics(response); + (0, utils_1.displayHttpDiagnostics)(response); } break; } core.info(`${name} - Attempt ${attempt} of ${maxAttempts} failed with error: ${errorMessage}`); - yield utils_1.sleep(utils_1.getExponentialRetryTimeInMilliseconds(attempt)); + yield (0, utils_1.sleep)((0, utils_1.getExponentialRetryTimeInMilliseconds)(attempt)); attempt++; } if (response) { - utils_1.displayHttpDiagnostics(response); + (0, utils_1.displayHttpDiagnostics)(response); } if (customErrorInformation) { throw Error(`${name} failed: ${customErrorInformation}`); @@ -1172,7 +1193,7 @@ function retry(name, operation, customErrorMessages, maxAttempts) { }); } exports.retry = retry; -function retryHttpClientRequest(name, method, customErrorMessages = new Map(), maxAttempts = config_variables_1.getRetryLimit()) { +function retryHttpClientRequest(name, method, customErrorMessages = new Map(), maxAttempts = (0, config_variables_1.getRetryLimit)()) { return __awaiter(this, void 0, void 0, function* () { return yield retry(name, method, customErrorMessages, maxAttempts); }); @@ -1214,14 +1235,14 @@ class StatusReporter { 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)}%)`); + (0, core_1.info)(`Total file count: ${this.totalNumberOfFilesToProcess} ---- Processed file #${this.processedCount} (${percentage.slice(0, percentage.indexOf('.') + 2)}%)`); }, this.displayFrequencyInMilliseconds); } // 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, chunkStartIndex, chunkEndIndex, totalUploadFileSize) { // display 1 decimal place without any rounding const percentage = this.formatPercentage(chunkEndIndex, totalUploadFileSize); - core_1.info(`Uploaded ${fileName} (${percentage.slice(0, percentage.indexOf('.') + 2)}%) bytes ${chunkStartIndex}:${chunkEndIndex}`); + (0, core_1.info)(`Uploaded ${fileName} (${percentage.slice(0, percentage.indexOf('.') + 2)}%) bytes ${chunkStartIndex}:${chunkEndIndex}`); } stop() { if (this.totalFileStatus) { @@ -1248,7 +1269,11 @@ exports.StatusReporter = StatusReporter; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -1261,7 +1286,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -1286,19 +1311,34 @@ exports.createGZipFileInBuffer = exports.createGZipFileOnDisk = void 0; const fs = __importStar(__nccwpck_require__(7147)); const zlib = __importStar(__nccwpck_require__(9796)); const util_1 = __nccwpck_require__(3837); -const stat = util_1.promisify(fs.stat); +const stat = (0, util_1.promisify)(fs.stat); /** * GZipping certain files that are already compressed will likely not yield further size reductions. Creating large temporary gzip * files then will just waste a lot of time before ultimately being discarded (especially for very large files). * If any of these types of files are encountered then on-disk gzip creation will be skipped and the original file will be uploaded as-is */ const gzipExemptFileExtensions = [ + '.gz', '.gzip', + '.tgz', + '.taz', + '.Z', + '.taZ', + '.bz2', + '.tbz', + '.tbz2', + '.tz2', + '.lz', + '.lzma', + '.tlz', + '.lzo', + '.xz', + '.txz', + '.zst', + '.zstd', + '.tzst', '.zip', - '.tar.lz', - '.tar.gz', - '.tar.bz2', - '.7z' + '.7z' // 7ZIP ]; /** * Creates a Gzip compressed file of an original file at the provided temporary filepath location @@ -1327,7 +1367,7 @@ function createGZipFileOnDisk(originalFilePath, tempFilePath) { outputStream.on('error', error => { // eslint-disable-next-line no-console console.log(error); - reject; + reject(error); }); }); }); @@ -1341,22 +1381,29 @@ exports.createGZipFileOnDisk = createGZipFileOnDisk; 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; + var _a, e_1, _b, _c; 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); + for (var _d = true, gzip_1 = __asyncValues(gzip), gzip_1_1; gzip_1_1 = yield gzip_1.next(), _a = gzip_1_1.done, !_a;) { + _c = gzip_1_1.value; + _d = false; + try { + const chunk = _c; + chunks.push(chunk); + } + finally { + _d = true; + } } } 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); + if (!_d && !_a && (_b = gzip_1.return)) yield _b.call(gzip_1); } finally { if (e_1) throw e_1.error; } } @@ -1376,7 +1423,11 @@ exports.createGZipFileInBuffer = createGZipFileInBuffer; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -1389,7 +1440,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -1418,10 +1469,10 @@ const http_client_1 = __nccwpck_require__(6255); const http_manager_1 = __nccwpck_require__(6527); const upload_gzip_1 = __nccwpck_require__(606); const requestUtils_1 = __nccwpck_require__(755); -const stat = util_1.promisify(fs.stat); +const stat = (0, util_1.promisify)(fs.stat); class UploadHttpClient { constructor() { - this.uploadHttpManager = new http_manager_1.HttpManager(config_variables_1.getUploadFileConcurrency(), '@actions/artifact-upload'); + this.uploadHttpManager = new http_manager_1.HttpManager((0, config_variables_1.getUploadFileConcurrency)(), '@actions/artifact-upload'); this.statusReporter = new status_reporter_1.StatusReporter(10000); } /** @@ -1437,28 +1488,30 @@ class UploadHttpClient { }; // calculate retention period if (options && options.retentionDays) { - const maxRetentionStr = config_variables_1.getRetentionDays(); - parameters.RetentionDays = utils_1.getProperRetention(options.retentionDays, maxRetentionStr); + const maxRetentionStr = (0, config_variables_1.getRetentionDays)(); + parameters.RetentionDays = (0, utils_1.getProperRetention)(options.retentionDays, maxRetentionStr); } const data = JSON.stringify(parameters, null, 2); - const artifactUrl = utils_1.getArtifactUrl(); + const artifactUrl = (0, 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); + const headers = (0, 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' + (0, config_variables_1.isGhes)() + ? 'Please reference [Enabling GitHub Actions for GitHub Enterprise Server](https://docs.github.com/en/enterprise-server@3.8/admin/github-actions/enabling-github-actions-for-github-enterprise-server) to ensure Actions storage is configured correctly.' + : '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 response = yield (0, 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); }); @@ -1471,8 +1524,8 @@ class UploadHttpClient { */ 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(); + const FILE_CONCURRENCY = (0, config_variables_1.getUploadFileConcurrency)(); + const MAX_CHUNK_SIZE = (0, 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 @@ -1562,7 +1615,7 @@ class UploadHttpClient { // with named pipes the file size is reported as zero in that case don't read the file in memory if (!isFIFO && totalFileSize < 65536) { core.debug(`${parameters.file} is less than 64k in size. Creating a gzip file in-memory to potentially reduce the upload size`); - const buffer = yield upload_gzip_1.createGZipFileInBuffer(parameters.file); + const buffer = yield (0, 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; @@ -1602,7 +1655,7 @@ class UploadHttpClient { const tempFile = yield tmp.file(); core.debug(`${parameters.file} is greater than 64k in size. Creating a gzip file on-disk ${tempFile.path} to potentially reduce the upload size`); // 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); + uploadFileSize = yield (0, 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 // for named pipes totalFileSize is zero, this assumes compression did help @@ -1675,22 +1728,22 @@ class UploadHttpClient { uploadChunk(httpClientIndex, resourceUrl, openStream, start, end, uploadFileSize, isGzip, totalFileSize) { return __awaiter(this, void 0, void 0, function* () { // open a new stream and read it to compute the digest - const digest = yield utils_1.digestForStream(openStream()); + const digest = yield (0, utils_1.digestForStream)(openStream()); // 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), digest); + const headers = (0, utils_1.getUploadHeaders)('application/octet-stream', true, isGzip, totalFileSize, end - start + 1, (0, utils_1.getContentRange)(start, end, uploadFileSize), digest); 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(); + const retryLimit = (0, 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); + (0, utils_1.displayHttpDiagnostics)(response); } core.info(`Retry limit has been reached for chunk at offset ${start} to ${resourceUrl}`); return true; @@ -1701,12 +1754,12 @@ class UploadHttpClient { 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); + yield (0, utils_1.sleep)(retryAfterValue); } else { - const backoffTime = utils_1.getExponentialRetryTimeInMilliseconds(retryCount); + const backoffTime = (0, 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); + yield (0, utils_1.sleep)(backoffTime); } core.info(`Finished backoff for retry #${retryCount}, continuing with upload`); return; @@ -1731,21 +1784,21 @@ class UploadHttpClient { // 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)) { + if ((0, utils_1.isSuccessStatusCode)(response.message.statusCode)) { return true; } - else if (utils_1.isRetryableStatusCode(response.message.statusCode)) { + else if ((0, 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)) + (0, utils_1.isThrottledStatusCode)(response.message.statusCode) + ? yield backOff((0, utils_1.tryGetRetryAfterValueTimeInMilliseconds)(response.message.headers)) : yield backOff(); } else { core.error(`Unexpected response. Unable to upload chunk to ${resourceUrl}`); - utils_1.displayHttpDiagnostics(response); + (0, utils_1.displayHttpDiagnostics)(response); return false; } } @@ -1758,14 +1811,14 @@ class UploadHttpClient { */ patchArtifactSize(size, artifactName) { return __awaiter(this, void 0, void 0, function* () { - const resourceUrl = new url_1.URL(utils_1.getArtifactUrl()); + const resourceUrl = new url_1.URL((0, 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); + const headers = (0, utils_1.getUploadHeaders)('application/json', false); // Extra information to display when a particular HTTP code is returned const customErrorMessages = new Map([ [ @@ -1774,7 +1827,7 @@ class UploadHttpClient { ] ]); // 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); + const response = yield (0, 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}`); }); @@ -1792,7 +1845,11 @@ exports.UploadHttpClient = UploadHttpClient; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -1805,7 +1862,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -1827,12 +1884,12 @@ function getUploadSpecification(artifactName, rootDirectory, artifactFiles) { if (!fs.existsSync(rootDirectory)) { throw new Error(`Provided rootDirectory ${rootDirectory} does not exist`); } - if (!fs.lstatSync(rootDirectory).isDirectory()) { + if (!fs.statSync(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); + rootDirectory = (0, path_1.normalize)(rootDirectory); + rootDirectory = (0, path_1.resolve)(rootDirectory); /* Example to demonstrate behavior @@ -1856,16 +1913,16 @@ function getUploadSpecification(artifactName, rootDirectory, artifactFiles) { if (!fs.existsSync(file)) { throw new Error(`File ${file} does not exist`); } - if (!fs.lstatSync(file).isDirectory()) { + if (!fs.statSync(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); + file = (0, path_1.normalize)(file); + file = (0, 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, ''); - path_and_artifact_name_validation_1.checkArtifactFilePath(uploadPath); + (0, path_and_artifact_name_validation_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 @@ -1878,12 +1935,12 @@ function getUploadSpecification(artifactName, rootDirectory, artifactFiles) { */ specifications.push({ absoluteFilePath: file, - uploadFilePath: path_1.join(artifactName, uploadPath) + uploadFilePath: (0, 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`); + (0, core_1.debug)(`Removing ${file} from rawSearchResults because it is a directory`); } } return specifications; @@ -1928,10 +1985,10 @@ function getExponentialRetryTimeInMilliseconds(retryCount) { throw new Error('RetryCount should not be negative'); } else if (retryCount === 0) { - return config_variables_1.getInitialRetryIntervalInMilliseconds(); + return (0, config_variables_1.getInitialRetryIntervalInMilliseconds)(); } - const minTime = config_variables_1.getInitialRetryIntervalInMilliseconds() * config_variables_1.getRetryMultiplier() * retryCount; - const maxTime = minTime * config_variables_1.getRetryMultiplier(); + const minTime = (0, config_variables_1.getInitialRetryIntervalInMilliseconds)() * (0, config_variables_1.getRetryMultiplier)() * retryCount; + const maxTime = minTime * (0, config_variables_1.getRetryMultiplier)(); // returns a random number between the minTime (inclusive) and the maxTime (exclusive) return Math.trunc(Math.random() * (maxTime - minTime) + minTime); } @@ -1999,13 +2056,13 @@ 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}`); + (0, 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`); + (0, 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`); + (0, 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; @@ -2089,13 +2146,13 @@ function getUploadHeaders(contentType, isKeepAlive, isGzip, uncompressedLength, exports.getUploadHeaders = getUploadHeaders; function createHttpClient(userAgent) { return new http_client_1.HttpClient(userAgent, [ - new auth_1.BearerCredentialHandler(config_variables_1.getRuntimeToken()) + new auth_1.BearerCredentialHandler((0, 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}`); + const artifactUrl = `${(0, config_variables_1.getRuntimeUrl)()}_apis/pipelines/workflows/${(0, config_variables_1.getWorkFlowRunId)()}/artifacts?api-version=${getApiVersion()}`; + (0, core_1.debug)(`Artifact Url: ${artifactUrl}`); return artifactUrl; } exports.getArtifactUrl = getArtifactUrl; @@ -2109,7 +2166,7 @@ exports.getArtifactUrl = getArtifactUrl; * 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 ##### + (0, 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)} @@ -2137,7 +2194,7 @@ 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})`); + (0, core_1.debug)(`${filePath} size:(${stats.size}) blksize:(${stats.blksize}) blocks:(${stats.blocks})`); return stats.size; }); } @@ -2156,7 +2213,7 @@ function getProperRetention(retentionInput, retentionSetting) { 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`); + (0, core_1.warning)(`Retention days is greater than the max value allowed by the repository setting, reduce retention to ${maxRetention} days`); retention = maxRetention; } } @@ -5069,6 +5126,29 @@ var Writable = (__nccwpck_require__(2781).Writable); var assert = __nccwpck_require__(9491); var debug = __nccwpck_require__(1133); +// Whether to use the native URL object or the legacy url module +var useNativeURL = false; +try { + assert(new URL()); +} +catch (error) { + useNativeURL = error.code === "ERR_INVALID_URL"; +} + +// URL fields to preserve in copy operations +var preservedUrlFields = [ + "auth", + "host", + "hostname", + "href", + "path", + "pathname", + "port", + "protocol", + "query", + "search", +]; + // Create handlers that pass events from native requests var events = ["abort", "aborted", "connect", "error", "socket", "timeout"]; var eventHandlers = Object.create(null); @@ -5078,19 +5158,20 @@ events.forEach(function (event) { }; }); +// Error types with codes var InvalidUrlError = createErrorType( "ERR_INVALID_URL", "Invalid URL", TypeError ); -// Error types with codes var RedirectionError = createErrorType( "ERR_FR_REDIRECTION_FAILURE", "Redirected request failed" ); var TooManyRedirectsError = createErrorType( "ERR_FR_TOO_MANY_REDIRECTS", - "Maximum number of redirects exceeded" + "Maximum number of redirects exceeded", + RedirectionError ); var MaxBodyLengthExceededError = createErrorType( "ERR_FR_MAX_BODY_LENGTH_EXCEEDED", @@ -5101,6 +5182,9 @@ var WriteAfterEndError = createErrorType( "write after end" ); +// istanbul ignore next +var destroy = Writable.prototype.destroy || noop; + // An HTTP(S) request that can be redirected function RedirectableRequest(options, responseCallback) { // Initialize the request @@ -5122,7 +5206,13 @@ function RedirectableRequest(options, responseCallback) { // React to responses of native requests var self = this; this._onNativeResponse = function (response) { - self._processResponse(response); + try { + self._processResponse(response); + } + catch (cause) { + self.emit("error", cause instanceof RedirectionError ? + cause : new RedirectionError({ cause: cause })); + } }; // Perform the first request @@ -5131,10 +5221,17 @@ function RedirectableRequest(options, responseCallback) { RedirectableRequest.prototype = Object.create(Writable.prototype); RedirectableRequest.prototype.abort = function () { - abortRequest(this._currentRequest); + destroyRequest(this._currentRequest); + this._currentRequest.abort(); this.emit("abort"); }; +RedirectableRequest.prototype.destroy = function (error) { + destroyRequest(this._currentRequest, error); + destroy.call(this, error); + return this; +}; + // Writes buffered data to the current native request RedirectableRequest.prototype.write = function (data, encoding, callback) { // Writing is not allowed if end has been called @@ -5247,6 +5344,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) { self.removeListener("abort", clearTimer); self.removeListener("error", clearTimer); self.removeListener("response", clearTimer); + self.removeListener("close", clearTimer); if (callback) { self.removeListener("timeout", callback); } @@ -5273,6 +5371,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) { this.on("abort", clearTimer); this.on("error", clearTimer); this.on("response", clearTimer); + this.on("close", clearTimer); return this; }; @@ -5331,8 +5430,7 @@ RedirectableRequest.prototype._performRequest = function () { var protocol = this._options.protocol; var nativeProtocol = this._options.nativeProtocols[protocol]; if (!nativeProtocol) { - this.emit("error", new TypeError("Unsupported protocol " + protocol)); - return; + throw new TypeError("Unsupported protocol " + protocol); } // If specified, use the agent corresponding to the protocol @@ -5424,15 +5522,14 @@ RedirectableRequest.prototype._processResponse = function (response) { } // The response is a redirect, so abort the current request - abortRequest(this._currentRequest); + destroyRequest(this._currentRequest); // Discard the remainder of the response to avoid waiting for data response.destroy(); // RFC7231§6.4: A client SHOULD detect and intervene // in cyclical redirections (i.e., "infinite" redirection loops). if (++this._redirectCount > this._options.maxRedirects) { - this.emit("error", new TooManyRedirectsError()); - return; + throw new TooManyRedirectsError(); } // Store the request headers if applicable @@ -5466,33 +5563,23 @@ RedirectableRequest.prototype._processResponse = function (response) { var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers); // If the redirect is relative, carry over the host of the last request - var currentUrlParts = url.parse(this._currentUrl); + var currentUrlParts = parseUrl(this._currentUrl); var currentHost = currentHostHeader || currentUrlParts.host; var currentUrl = /^\w+:/.test(location) ? this._currentUrl : url.format(Object.assign(currentUrlParts, { host: currentHost })); - // Determine the URL of the redirection - var redirectUrl; - try { - redirectUrl = url.resolve(currentUrl, location); - } - catch (cause) { - this.emit("error", new RedirectionError({ cause: cause })); - return; - } - // Create the redirected request - debug("redirecting to", redirectUrl); + var redirectUrl = resolveUrl(location, currentUrl); + debug("redirecting to", redirectUrl.href); this._isRedirect = true; - var redirectUrlParts = url.parse(redirectUrl); - Object.assign(this._options, redirectUrlParts); + spreadUrlObject(redirectUrl, this._options); // Drop confidential headers when redirecting to a less secure protocol // or to a different domain that is not a superdomain - if (redirectUrlParts.protocol !== currentUrlParts.protocol && - redirectUrlParts.protocol !== "https:" || - redirectUrlParts.host !== currentHost && - !isSubdomain(redirectUrlParts.host, currentHost)) { + if (redirectUrl.protocol !== currentUrlParts.protocol && + redirectUrl.protocol !== "https:" || + redirectUrl.host !== currentHost && + !isSubdomain(redirectUrl.host, currentHost)) { removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers); } @@ -5507,23 +5594,12 @@ RedirectableRequest.prototype._processResponse = function (response) { method: method, headers: requestHeaders, }; - try { - beforeRedirect(this._options, responseDetails, requestDetails); - } - catch (err) { - this.emit("error", err); - return; - } + beforeRedirect(this._options, responseDetails, requestDetails); this._sanitizeOptions(this._options); } // Perform the redirected request - try { - this._performRequest(); - } - catch (cause) { - this.emit("error", new RedirectionError({ cause: cause })); - } + this._performRequest(); }; // Wraps the key/value object of protocols with redirect functionality @@ -5543,27 +5619,16 @@ function wrap(protocols) { // Executes a request, following redirects function request(input, options, callback) { - // Parse parameters - if (isString(input)) { - var parsed; - try { - parsed = urlToOptions(new URL(input)); - } - catch (err) { - /* istanbul ignore next */ - parsed = url.parse(input); - } - if (!isString(parsed.protocol)) { - throw new InvalidUrlError({ input }); - } - input = parsed; + // Parse parameters, ensuring that input is an object + if (isURL(input)) { + input = spreadUrlObject(input); } - else if (URL && (input instanceof URL)) { - input = urlToOptions(input); + else if (isString(input)) { + input = spreadUrlObject(parseUrl(input)); } else { callback = options; - options = input; + options = validateUrl(input); input = { protocol: protocol }; } if (isFunction(options)) { @@ -5602,27 +5667,57 @@ function wrap(protocols) { return exports; } -/* istanbul ignore next */ function noop() { /* empty */ } -// from https://github.com/nodejs/node/blob/master/lib/internal/url.js -function urlToOptions(urlObject) { - var options = { - protocol: urlObject.protocol, - hostname: urlObject.hostname.startsWith("[") ? - /* istanbul ignore next */ - urlObject.hostname.slice(1, -1) : - urlObject.hostname, - hash: urlObject.hash, - search: urlObject.search, - pathname: urlObject.pathname, - path: urlObject.pathname + urlObject.search, - href: urlObject.href, - }; - if (urlObject.port !== "") { - options.port = Number(urlObject.port); +function parseUrl(input) { + var parsed; + /* istanbul ignore else */ + if (useNativeURL) { + parsed = new URL(input); + } + else { + // Ensure the URL is valid and absolute + parsed = validateUrl(url.parse(input)); + if (!isString(parsed.protocol)) { + throw new InvalidUrlError({ input }); + } + } + return parsed; +} + +function resolveUrl(relative, base) { + /* istanbul ignore next */ + return useNativeURL ? new URL(relative, base) : parseUrl(url.resolve(base, relative)); +} + +function validateUrl(input) { + if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) { + throw new InvalidUrlError({ input: input.href || input }); + } + if (/^\[/.test(input.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input.host)) { + throw new InvalidUrlError({ input: input.href || input }); + } + return input; +} + +function spreadUrlObject(urlObject, target) { + var spread = target || {}; + for (var key of preservedUrlFields) { + spread[key] = urlObject[key]; + } + + // Fix IPv6 hostname + if (spread.hostname.startsWith("[")) { + spread.hostname = spread.hostname.slice(1, -1); } - return options; + // Ensure port is a number + if (spread.port !== "") { + spread.port = Number(spread.port); + } + // Concatenate path + spread.path = spread.search ? spread.pathname + spread.search : spread.pathname; + + return spread; } function removeMatchingHeaders(regex, headers) { @@ -5648,17 +5743,25 @@ function createErrorType(code, message, baseClass) { // Attach constructor and set default properties CustomError.prototype = new (baseClass || Error)(); - CustomError.prototype.constructor = CustomError; - CustomError.prototype.name = "Error [" + code + "]"; + Object.defineProperties(CustomError.prototype, { + constructor: { + value: CustomError, + enumerable: false, + }, + name: { + value: "Error [" + code + "]", + enumerable: false, + }, + }); return CustomError; } -function abortRequest(request) { +function destroyRequest(request, error) { for (var event of events) { request.removeListener(event, eventHandlers[event]); } request.on("error", noop); - request.abort(); + request.destroy(error); } function isSubdomain(subdomain, domain) { @@ -5679,6 +5782,10 @@ function isBuffer(value) { return typeof value === "object" && ("length" in value); } +function isURL(value) { + return URL && value instanceof URL; +} + // Exports module.exports = wrap({ http: http, https: https }); module.exports.wrap = wrap; @@ -31934,12 +32041,19 @@ const publishEndpoint = `${serverEndpoint}/transformations/libraries/publish`; const listTransformationsEndpoint = `${serverEndpoint}/transformations`; const listLibrariesEndpoint = `${serverEndpoint}/libraries`; +const defaultHeader = { + "user-agent": "transformationAction" +} + async function getAllTransformations() { return axios.default.get(listTransformationsEndpoint, { auth: { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, }); } @@ -31949,10 +32063,14 @@ async function getAllLibraries() { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, }); } -async function createTransformer(name, description, code, language) { +async function createTransformation(name, description, code, language) { + core.info(`Created transformation: ${name}`); return axios.default.post( `${createTransformerEndpoint}?publish=false`, { @@ -31966,11 +32084,15 @@ async function createTransformer(name, description, code, language) { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, } ); } -async function updateTransformer(id, description, code, language) { +async function updateTransformation(id, name, description, code, language) { + core.info(`Updated transformation: ${name}`); return axios.default.post( `${createTransformerEndpoint}/${id}?publish=false`, { @@ -31983,6 +32105,9 @@ async function updateTransformer(id, description, code, language) { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, } ); } @@ -32001,6 +32126,9 @@ async function createLibrary(name, description, code, language) { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, } ); } @@ -32018,6 +32146,9 @@ async function updateLibrary(id, description, code, language) { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, } ); } @@ -32034,6 +32165,9 @@ async function testTransformationAndLibrary(transformations, libraries) { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, } ); } @@ -32051,6 +32185,9 @@ async function publish(transformations, libraries, commitId) { username: core.getInput("email"), password: core.getInput("accessToken"), }, + headers: { + ...defaultHeader + }, } ); } @@ -32058,9 +32195,9 @@ async function publish(transformations, libraries, commitId) { module.exports = { getAllTransformations, getAllLibraries, - createTransformer, + createTransformation, createLibrary, - updateTransformer, + updateTransformation, updateLibrary, testTransformationAndLibrary, publish, @@ -32482,7 +32619,7 @@ exports.makeObjectWithoutPrototype = makeObjectWithoutPrototype; /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; -// Axios v1.4.0 Copyright (c) 2023 Matt Zabriskie and contributors +// Axios v1.6.4 Copyright (c) 2024 Matt Zabriskie and contributors const FormData$1 = __nccwpck_require__(4334); @@ -33052,8 +33189,9 @@ const reduceDescriptors = (obj, reducer) => { const reducedDescriptors = {}; forEach(descriptors, (descriptor, name) => { - if (reducer(descriptor, name, obj) !== false) { - reducedDescriptors[name] = descriptor; + let ret; + if ((ret = reducer(descriptor, name, obj)) !== false) { + reducedDescriptors[name] = ret || descriptor; } }); @@ -33179,7 +33317,7 @@ const isAsyncFn = kindOfTest('AsyncFunction'); const isThenable = (thing) => thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch); -const utils = { +const utils$1 = { isArray, isArrayBuffer, isBuffer, @@ -33261,7 +33399,7 @@ function AxiosError(message, code, config, request, response) { response && (this.response = response); } -utils.inherits(AxiosError, Error, { +utils$1.inherits(AxiosError, Error, { toJSON: function toJSON() { return { // Standard @@ -33276,7 +33414,7 @@ utils.inherits(AxiosError, Error, { columnNumber: this.columnNumber, stack: this.stack, // Axios - config: utils.toJSONObject(this.config), + config: utils$1.toJSONObject(this.config), code: this.code, status: this.response && this.response.status ? this.response.status : null }; @@ -33311,7 +33449,7 @@ Object.defineProperty(prototype$1, 'isAxiosError', {value: true}); AxiosError.from = (error, code, config, request, response, customProps) => { const axiosError = Object.create(prototype$1); - utils.toFlatObject(error, axiosError, function filter(obj) { + utils$1.toFlatObject(error, axiosError, function filter(obj) { return obj !== Error.prototype; }, prop => { return prop !== 'isAxiosError'; @@ -33336,7 +33474,7 @@ AxiosError.from = (error, code, config, request, response, customProps) => { * @returns {boolean} */ function isVisitable(thing) { - return utils.isPlainObject(thing) || utils.isArray(thing); + return utils$1.isPlainObject(thing) || utils$1.isArray(thing); } /** @@ -33347,7 +33485,7 @@ function isVisitable(thing) { * @returns {string} the key without the brackets. */ function removeBrackets(key) { - return utils.endsWith(key, '[]') ? key.slice(0, -2) : key; + return utils$1.endsWith(key, '[]') ? key.slice(0, -2) : key; } /** @@ -33376,10 +33514,10 @@ function renderKey(path, key, dots) { * @returns {boolean} */ function isFlatArray(arr) { - return utils.isArray(arr) && !arr.some(isVisitable); + return utils$1.isArray(arr) && !arr.some(isVisitable); } -const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) { +const predicates = utils$1.toFlatObject(utils$1, {}, null, function filter(prop) { return /^is[A-Z]/.test(prop); }); @@ -33407,7 +33545,7 @@ const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) { * @returns */ function toFormData(obj, formData, options) { - if (!utils.isObject(obj)) { + if (!utils$1.isObject(obj)) { throw new TypeError('target must be an object'); } @@ -33415,13 +33553,13 @@ function toFormData(obj, formData, options) { formData = formData || new (FormData__default["default"] || FormData)(); // eslint-disable-next-line no-param-reassign - options = utils.toFlatObject(options, { + options = utils$1.toFlatObject(options, { metaTokens: true, dots: false, indexes: false }, false, function defined(option, source) { // eslint-disable-next-line no-eq-null,eqeqeq - return !utils.isUndefined(source[option]); + return !utils$1.isUndefined(source[option]); }); const metaTokens = options.metaTokens; @@ -33430,24 +33568,24 @@ function toFormData(obj, formData, options) { const dots = options.dots; const indexes = options.indexes; const _Blob = options.Blob || typeof Blob !== 'undefined' && Blob; - const useBlob = _Blob && utils.isSpecCompliantForm(formData); + const useBlob = _Blob && utils$1.isSpecCompliantForm(formData); - if (!utils.isFunction(visitor)) { + if (!utils$1.isFunction(visitor)) { throw new TypeError('visitor must be a function'); } function convertValue(value) { if (value === null) return ''; - if (utils.isDate(value)) { + if (utils$1.isDate(value)) { return value.toISOString(); } - if (!useBlob && utils.isBlob(value)) { + if (!useBlob && utils$1.isBlob(value)) { throw new AxiosError('Blob is not supported. Use a Buffer instead.'); } - if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) { + if (utils$1.isArrayBuffer(value) || utils$1.isTypedArray(value)) { return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); } @@ -33468,20 +33606,20 @@ function toFormData(obj, formData, options) { let arr = value; if (value && !path && typeof value === 'object') { - if (utils.endsWith(key, '{}')) { + if (utils$1.endsWith(key, '{}')) { // eslint-disable-next-line no-param-reassign key = metaTokens ? key : key.slice(0, -2); // eslint-disable-next-line no-param-reassign value = JSON.stringify(value); } else if ( - (utils.isArray(value) && isFlatArray(value)) || - ((utils.isFileList(value) || utils.endsWith(key, '[]')) && (arr = utils.toArray(value)) + (utils$1.isArray(value) && isFlatArray(value)) || + ((utils$1.isFileList(value) || utils$1.endsWith(key, '[]')) && (arr = utils$1.toArray(value)) )) { // eslint-disable-next-line no-param-reassign key = removeBrackets(key); arr.forEach(function each(el, index) { - !(utils.isUndefined(el) || el === null) && formData.append( + !(utils$1.isUndefined(el) || el === null) && formData.append( // eslint-disable-next-line no-nested-ternary indexes === true ? renderKey([key], index, dots) : (indexes === null ? key : key + '[]'), convertValue(el) @@ -33509,7 +33647,7 @@ function toFormData(obj, formData, options) { }); function build(value, path) { - if (utils.isUndefined(value)) return; + if (utils$1.isUndefined(value)) return; if (stack.indexOf(value) !== -1) { throw Error('Circular reference detected in ' + path.join('.')); @@ -33517,9 +33655,9 @@ function toFormData(obj, formData, options) { stack.push(value); - utils.forEach(value, function each(el, key) { - const result = !(utils.isUndefined(el) || el === null) && visitor.call( - formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers + utils$1.forEach(value, function each(el, key) { + const result = !(utils$1.isUndefined(el) || el === null) && visitor.call( + formData, el, utils$1.isString(key) ? key.trim() : key, path, exposedHelpers ); if (result === true) { @@ -33530,7 +33668,7 @@ function toFormData(obj, formData, options) { stack.pop(); } - if (!utils.isObject(obj)) { + if (!utils$1.isObject(obj)) { throw new TypeError('data must be an object'); } @@ -33634,7 +33772,7 @@ function buildURL(url, params, options) { if (serializeFn) { serializedParams = serializeFn(params, options); } else { - serializedParams = utils.isURLSearchParams(params) ? + serializedParams = utils$1.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams(params, options).toString(_encode); } @@ -33709,7 +33847,7 @@ class InterceptorManager { * @returns {void} */ forEach(fn) { - utils.forEach(this.handlers, function forEachHandler(h) { + utils$1.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } @@ -33727,7 +33865,7 @@ const transitionalDefaults = { const URLSearchParams = url__default["default"].URLSearchParams; -const platform = { +const platform$1 = { isNode: true, classes: { URLSearchParams, @@ -33737,10 +33875,64 @@ const platform = { protocols: [ 'http', 'https', 'file', 'data' ] }; +const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined'; + +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + * nativescript + * navigator.product -> 'NativeScript' or 'NS' + * + * @returns {boolean} + */ +const hasStandardBrowserEnv = ( + (product) => { + return hasBrowserEnv && ['ReactNative', 'NativeScript', 'NS'].indexOf(product) < 0 + })(typeof navigator !== 'undefined' && navigator.product); + +/** + * Determine if we're running in a standard browser webWorker environment + * + * Although the `isStandardBrowserEnv` method indicates that + * `allows axios to run in a web worker`, the WebWorker will still be + * filtered out due to its judgment standard + * `typeof window !== 'undefined' && typeof document !== 'undefined'`. + * This leads to a problem when axios post `FormData` in webWorker + */ +const hasStandardBrowserWebWorkerEnv = (() => { + return ( + typeof WorkerGlobalScope !== 'undefined' && + // eslint-disable-next-line no-undef + self instanceof WorkerGlobalScope && + typeof self.importScripts === 'function' + ); +})(); + +const utils = /*#__PURE__*/Object.freeze({ + __proto__: null, + hasBrowserEnv: hasBrowserEnv, + hasStandardBrowserWebWorkerEnv: hasStandardBrowserWebWorkerEnv, + hasStandardBrowserEnv: hasStandardBrowserEnv +}); + +const platform = { + ...utils, + ...platform$1 +}; + function toURLEncodedForm(data, options) { return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({ visitor: function(value, key, path, helpers) { - if (utils.isBuffer(value)) { + if (platform.isNode && utils$1.isBuffer(value)) { this.append(key, value.toString('base64')); return false; } @@ -33762,7 +33954,7 @@ function parsePropPath(name) { // foo.x.y.z // foo-x-y-z // foo x y z - return utils.matchAll(/\w+|\[(\w*)]/g, name).map(match => { + return utils$1.matchAll(/\w+|\[(\w*)]/g, name).map(match => { return match[0] === '[]' ? '' : match[1] || match[0]; }); } @@ -33797,12 +33989,15 @@ function arrayToObject(arr) { function formDataToJSON(formData) { function buildPath(path, value, target, index) { let name = path[index++]; + + if (name === '__proto__') return true; + const isNumericKey = Number.isFinite(+name); const isLast = index >= path.length; - name = !name && utils.isArray(target) ? target.length : name; + name = !name && utils$1.isArray(target) ? target.length : name; if (isLast) { - if (utils.hasOwnProp(target, name)) { + if (utils$1.hasOwnProp(target, name)) { target[name] = [target[name], value]; } else { target[name] = value; @@ -33811,23 +34006,23 @@ function formDataToJSON(formData) { return !isNumericKey; } - if (!target[name] || !utils.isObject(target[name])) { + if (!target[name] || !utils$1.isObject(target[name])) { target[name] = []; } const result = buildPath(path, value, target[name], index); - if (result && utils.isArray(target[name])) { + if (result && utils$1.isArray(target[name])) { target[name] = arrayToObject(target[name]); } return !isNumericKey; } - if (utils.isFormData(formData) && utils.isFunction(formData.entries)) { + if (utils$1.isFormData(formData) && utils$1.isFunction(formData.entries)) { const obj = {}; - utils.forEachEntry(formData, (name, value) => { + utils$1.forEachEntry(formData, (name, value) => { buildPath(parsePropPath(name), value, obj, 0); }); @@ -33837,10 +34032,6 @@ function formDataToJSON(formData) { return null; } -const DEFAULT_CONTENT_TYPE = { - 'Content-Type': undefined -}; - /** * It takes a string, tries to parse it, and if it fails, it returns the stringified version * of the input @@ -33852,10 +34043,10 @@ const DEFAULT_CONTENT_TYPE = { * @returns {string} A stringified version of the rawValue. */ function stringifySafely(rawValue, parser, encoder) { - if (utils.isString(rawValue)) { + if (utils$1.isString(rawValue)) { try { (parser || JSON.parse)(rawValue); - return utils.trim(rawValue); + return utils$1.trim(rawValue); } catch (e) { if (e.name !== 'SyntaxError') { throw e; @@ -33875,13 +34066,13 @@ const defaults = { transformRequest: [function transformRequest(data, headers) { const contentType = headers.getContentType() || ''; const hasJSONContentType = contentType.indexOf('application/json') > -1; - const isObjectPayload = utils.isObject(data); + const isObjectPayload = utils$1.isObject(data); - if (isObjectPayload && utils.isHTMLForm(data)) { + if (isObjectPayload && utils$1.isHTMLForm(data)) { data = new FormData(data); } - const isFormData = utils.isFormData(data); + const isFormData = utils$1.isFormData(data); if (isFormData) { if (!hasJSONContentType) { @@ -33890,18 +34081,18 @@ const defaults = { return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data; } - if (utils.isArrayBuffer(data) || - utils.isBuffer(data) || - utils.isStream(data) || - utils.isFile(data) || - utils.isBlob(data) + if (utils$1.isArrayBuffer(data) || + utils$1.isBuffer(data) || + utils$1.isStream(data) || + utils$1.isFile(data) || + utils$1.isBlob(data) ) { return data; } - if (utils.isArrayBufferView(data)) { + if (utils$1.isArrayBufferView(data)) { return data.buffer; } - if (utils.isURLSearchParams(data)) { + if (utils$1.isURLSearchParams(data)) { headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false); return data.toString(); } @@ -33913,7 +34104,7 @@ const defaults = { return toURLEncodedForm(data, this.formSerializer).toString(); } - if ((isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) { + if ((isFileList = utils$1.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1) { const _FormData = this.env && this.env.FormData; return toFormData( @@ -33937,7 +34128,7 @@ const defaults = { const forcedJSONParsing = transitional && transitional.forcedJSONParsing; const JSONRequested = this.responseType === 'json'; - if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) { + if (data && utils$1.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) { const silentJSONParsing = transitional && transitional.silentJSONParsing; const strictJSONParsing = !silentJSONParsing && JSONRequested; @@ -33979,24 +34170,21 @@ const defaults = { headers: { common: { - 'Accept': 'application/json, text/plain, */*' + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': undefined } } }; -utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { +utils$1.forEach(['delete', 'get', 'head', 'post', 'put', 'patch'], (method) => { defaults.headers[method] = {}; }); -utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { - defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); -}); - const defaults$1 = defaults; // RawAxiosHeaders whose duplicates are ignored by node // c.f. https://nodejs.org/api/http.html#http_message_headers -const ignoreDuplicateOf = utils.toObjectSet([ +const ignoreDuplicateOf = utils$1.toObjectSet([ 'age', 'authorization', 'content-length', 'content-type', 'etag', 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 'last-modified', 'location', 'max-forwards', 'proxy-authorization', @@ -34057,7 +34245,7 @@ function normalizeValue(value) { return value; } - return utils.isArray(value) ? value.map(normalizeValue) : String(value); + return utils$1.isArray(value) ? value.map(normalizeValue) : String(value); } function parseTokens(str) { @@ -34075,7 +34263,7 @@ function parseTokens(str) { const isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { - if (utils.isFunction(filter)) { + if (utils$1.isFunction(filter)) { return filter.call(this, value, header); } @@ -34083,13 +34271,13 @@ function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { value = header; } - if (!utils.isString(value)) return; + if (!utils$1.isString(value)) return; - if (utils.isString(filter)) { + if (utils$1.isString(filter)) { return value.indexOf(filter) !== -1; } - if (utils.isRegExp(filter)) { + if (utils$1.isRegExp(filter)) { return filter.test(value); } } @@ -34102,7 +34290,7 @@ function formatHeader(header) { } function buildAccessors(obj, header) { - const accessorName = utils.toCamelCase(' ' + header); + const accessorName = utils$1.toCamelCase(' ' + header); ['get', 'set', 'has'].forEach(methodName => { Object.defineProperty(obj, methodName + accessorName, { @@ -34129,7 +34317,7 @@ class AxiosHeaders { throw new Error('header name must be a non-empty string'); } - const key = utils.findKey(self, lHeader); + const key = utils$1.findKey(self, lHeader); if(!key || self[key] === undefined || _rewrite === true || (_rewrite === undefined && self[key] !== false)) { self[key || _header] = normalizeValue(_value); @@ -34137,11 +34325,11 @@ class AxiosHeaders { } const setHeaders = (headers, _rewrite) => - utils.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); + utils$1.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); - if (utils.isPlainObject(header) || header instanceof this.constructor) { + if (utils$1.isPlainObject(header) || header instanceof this.constructor) { setHeaders(header, valueOrRewrite); - } else if(utils.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { + } else if(utils$1.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { setHeaders(parseHeaders(header), valueOrRewrite); } else { header != null && setHeader(valueOrRewrite, header, rewrite); @@ -34154,7 +34342,7 @@ class AxiosHeaders { header = normalizeHeader(header); if (header) { - const key = utils.findKey(this, header); + const key = utils$1.findKey(this, header); if (key) { const value = this[key]; @@ -34167,11 +34355,11 @@ class AxiosHeaders { return parseTokens(value); } - if (utils.isFunction(parser)) { + if (utils$1.isFunction(parser)) { return parser.call(this, value, key); } - if (utils.isRegExp(parser)) { + if (utils$1.isRegExp(parser)) { return parser.exec(value); } @@ -34184,7 +34372,7 @@ class AxiosHeaders { header = normalizeHeader(header); if (header) { - const key = utils.findKey(this, header); + const key = utils$1.findKey(this, header); return !!(key && this[key] !== undefined && (!matcher || matchHeaderValue(this, this[key], key, matcher))); } @@ -34200,7 +34388,7 @@ class AxiosHeaders { _header = normalizeHeader(_header); if (_header) { - const key = utils.findKey(self, _header); + const key = utils$1.findKey(self, _header); if (key && (!matcher || matchHeaderValue(self, self[key], key, matcher))) { delete self[key]; @@ -34210,7 +34398,7 @@ class AxiosHeaders { } } - if (utils.isArray(header)) { + if (utils$1.isArray(header)) { header.forEach(deleteHeader); } else { deleteHeader(header); @@ -34239,8 +34427,8 @@ class AxiosHeaders { const self = this; const headers = {}; - utils.forEach(this, (value, header) => { - const key = utils.findKey(headers, header); + utils$1.forEach(this, (value, header) => { + const key = utils$1.findKey(headers, header); if (key) { self[key] = normalizeValue(value); @@ -34269,8 +34457,8 @@ class AxiosHeaders { toJSON(asStrings) { const obj = Object.create(null); - utils.forEach(this, (value, header) => { - value != null && value !== false && (obj[header] = asStrings && utils.isArray(value) ? value.join(', ') : value); + utils$1.forEach(this, (value, header) => { + value != null && value !== false && (obj[header] = asStrings && utils$1.isArray(value) ? value.join(', ') : value); }); return obj; @@ -34317,7 +34505,7 @@ class AxiosHeaders { } } - utils.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); + utils$1.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); return this; } @@ -34325,8 +34513,18 @@ class AxiosHeaders { AxiosHeaders.accessor(['Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization']); -utils.freezeMethods(AxiosHeaders.prototype); -utils.freezeMethods(AxiosHeaders); +// reserved names hotfix +utils$1.reduceDescriptors(AxiosHeaders.prototype, ({value}, key) => { + let mapped = key[0].toUpperCase() + key.slice(1); // map `set` => `Set` + return { + get: () => value, + set(headerValue) { + this[mapped] = headerValue; + } + } +}); + +utils$1.freezeMethods(AxiosHeaders); const AxiosHeaders$1 = AxiosHeaders; @@ -34344,7 +34542,7 @@ function transformData(fns, response) { const headers = AxiosHeaders$1.from(context.headers); let data = context.data; - utils.forEach(fns, function transform(fn) { + utils$1.forEach(fns, function transform(fn) { data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); }); @@ -34372,7 +34570,7 @@ function CanceledError(message, config, request) { this.name = 'CanceledError'; } -utils.inherits(CanceledError, AxiosError, { +utils$1.inherits(CanceledError, AxiosError, { __CANCEL__: true }); @@ -34424,7 +34622,7 @@ function isAbsoluteURL(url) { */ function combineURLs(baseURL, relativeURL) { return relativeURL - ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') + ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL; } @@ -34445,7 +34643,7 @@ function buildFullPath(baseURL, requestedURL) { return requestedURL; } -const VERSION = "1.4.0"; +const VERSION = "1.6.4"; function parseProtocol(url) { const match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url); @@ -34586,7 +34784,7 @@ const kInternals = Symbol('internals'); class AxiosTransformStream extends stream__default["default"].Transform{ constructor(options) { - options = utils.toFlatObject(options, { + options = utils$1.toFlatObject(options, { maxRate: 0, chunkSize: 64 * 1024, minChunkSize: 100, @@ -34594,7 +34792,7 @@ class AxiosTransformStream extends stream__default["default"].Transform{ ticksRate: 2, samplesCount: 15 }, null, (prop, source) => { - return !utils.isUndefined(source[prop]); + return !utils$1.isUndefined(source[prop]); }); super({ @@ -34783,7 +34981,7 @@ const readBlob = async function* (blob) { const readBlob$1 = readBlob; -const BOUNDARY_ALPHABET = utils.ALPHABET.ALPHA_DIGIT + '-_'; +const BOUNDARY_ALPHABET = utils$1.ALPHABET.ALPHA_DIGIT + '-_'; const textEncoder = new util.TextEncoder(); @@ -34794,7 +34992,7 @@ const CRLF_BYTES_COUNT = 2; class FormDataPart { constructor(name, value) { const {escapeName} = this.constructor; - const isStringValue = utils.isString(value); + const isStringValue = utils$1.isString(value); let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${ !isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : '' @@ -34821,7 +35019,7 @@ class FormDataPart { const {value} = this; - if(utils.isTypedArray(value)) { + if(utils$1.isTypedArray(value)) { yield value; } else { yield* readBlob$1(value); @@ -34843,10 +35041,10 @@ const formDataToStream = (form, headersHandler, options) => { const { tag = 'form-data-boundary', size = 25, - boundary = tag + '-' + utils.generateString(size, BOUNDARY_ALPHABET) + boundary = tag + '-' + utils$1.generateString(size, BOUNDARY_ALPHABET) } = options || {}; - if(!utils.isFormData(form)) { + if(!utils$1.isFormData(form)) { throw TypeError('FormData instance required'); } @@ -34866,7 +35064,7 @@ const formDataToStream = (form, headersHandler, options) => { contentLength += boundaryBytes.byteLength * parts.length; - contentLength = utils.toFiniteNumber(contentLength); + contentLength = utils$1.toFiniteNumber(contentLength); const computedHeaders = { 'Content-Type': `multipart/form-data; boundary=${boundary}` @@ -34916,7 +35114,7 @@ class ZlibHeaderTransformStream extends stream__default["default"].Transform { const ZlibHeaderTransformStream$1 = ZlibHeaderTransformStream; const callbackify = (fn, reducer) => { - return utils.isAsyncFn(fn) ? function (...args) { + return utils$1.isAsyncFn(fn) ? function (...args) { const cb = args.pop(); fn.apply(this, args).then((value) => { try { @@ -34940,7 +35138,7 @@ const brotliOptions = { finishFlush: zlib__default["default"].constants.BROTLI_OPERATION_FLUSH }; -const isBrotliSupported = utils.isFunction(zlib__default["default"].createBrotliDecompress); +const isBrotliSupported = utils$1.isFunction(zlib__default["default"].createBrotliDecompress); const {http: httpFollow, https: httpsFollow} = followRedirects__default["default"]; @@ -35020,7 +35218,7 @@ function setProxy(options, configProxy, location) { }; } -const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process'; +const isHttpAdapterSupported = typeof process !== 'undefined' && utils$1.kindOf(process) === 'process'; // temporary hotfix @@ -35049,6 +35247,18 @@ const wrapAsync = (asyncExecutor) => { }) }; +const resolveFamily = ({address, family}) => { + if (!utils$1.isString(address)) { + throw TypeError('address must be a string'); + } + return ({ + address, + family: family || (address.indexOf('.') < 0 ? 6 : 4) + }); +}; + +const buildAddressEntry = (address, family) => resolveFamily(utils$1.isObject(address) ? address : {address, family}); + /*eslint consistent-return:0*/ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) { @@ -35059,15 +35269,16 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { let rejected = false; let req; - if (lookup && utils.isAsyncFn(lookup)) { - lookup = callbackify$1(lookup, (entry) => { - if(utils.isString(entry)) { - entry = [entry, entry.indexOf('.') < 0 ? 6 : 4]; - } else if (!utils.isArray(entry)) { - throw new TypeError('lookup async function must return an array [ip: string, family: number]]') - } - return entry; - }); + if (lookup) { + const _lookup = callbackify$1(lookup, (value) => utils$1.isArray(value) ? value : [value]); + // hotfix to support opt.all option which is required for node 20.x + lookup = (hostname, opt, cb) => { + _lookup(hostname, opt, (err, arg0, arg1) => { + const addresses = utils$1.isArray(arg0) ? arg0.map(addr => buildAddressEntry(addr)) : [buildAddressEntry(arg0, arg1)]; + + opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family); + }); + }; } // temporary internal emitter until the AxiosRequest class will be implemented @@ -35135,7 +35346,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { convertedData = convertedData.toString(responseEncoding); if (!responseEncoding || responseEncoding === 'utf8') { - convertedData = utils.stripBOM(convertedData); + convertedData = utils$1.stripBOM(convertedData); } } else if (responseType === 'stream') { convertedData = stream__default["default"].Readable.from(convertedData); @@ -35173,7 +35384,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { let maxDownloadRate = undefined; // support for spec compliant FormData objects - if (utils.isSpecCompliantForm(data)) { + if (utils$1.isSpecCompliantForm(data)) { const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i); data = formDataToStream$1(data, (formHeaders) => { @@ -35183,7 +35394,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { boundary: userBoundary && userBoundary[1] || undefined }); // support for https://www.npmjs.com/package/form-data api - } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) { + } else if (utils$1.isFormData(data) && utils$1.isFunction(data.getHeaders)) { headers.set(data.getHeaders()); if (!headers.hasContentLength()) { @@ -35194,14 +35405,14 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } catch (e) { } } - } else if (utils.isBlob(data)) { + } else if (utils$1.isBlob(data)) { data.size && headers.setContentType(data.type || 'application/octet-stream'); headers.setContentLength(data.size || 0); data = stream__default["default"].Readable.from(readBlob$1(data)); - } else if (data && !utils.isStream(data)) { - if (Buffer.isBuffer(data)) ; else if (utils.isArrayBuffer(data)) { + } else if (data && !utils$1.isStream(data)) { + if (Buffer.isBuffer(data)) ; else if (utils$1.isArrayBuffer(data)) { data = Buffer.from(new Uint8Array(data)); - } else if (utils.isString(data)) { + } else if (utils$1.isString(data)) { data = Buffer.from(data, 'utf-8'); } else { return reject(new AxiosError( @@ -35223,9 +35434,9 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } } - const contentLength = utils.toFiniteNumber(headers.getContentLength()); + const contentLength = utils$1.toFiniteNumber(headers.getContentLength()); - if (utils.isArray(maxRate)) { + if (utils$1.isArray(maxRate)) { maxUploadRate = maxRate[0]; maxDownloadRate = maxRate[1]; } else { @@ -35233,14 +35444,14 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } if (data && (onUploadProgress || maxUploadRate)) { - if (!utils.isStream(data)) { + if (!utils$1.isStream(data)) { data = stream__default["default"].Readable.from(data, {objectMode: false}); } data = stream__default["default"].pipeline([data, new AxiosTransformStream$1({ length: contentLength, - maxRate: utils.toFiniteNumber(maxUploadRate) - })], utils.noop); + maxRate: utils$1.toFiniteNumber(maxUploadRate) + })], utils$1.noop); onUploadProgress && data.on('progress', progress => { onUploadProgress(Object.assign(progress, { @@ -35294,11 +35505,13 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { auth, protocol, family, - lookup, beforeRedirect: dispatchBeforeRedirect, beforeRedirects: {} }; + // cacheable-lookup integration hotfix + !utils$1.isUndefined(lookup) && (options.lookup = lookup); + if (config.socketPath) { options.socketPath = config.socketPath; } else { @@ -35345,8 +35558,8 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { if (onDownloadProgress) { const transformStream = new AxiosTransformStream$1({ - length: utils.toFiniteNumber(responseLength), - maxRate: utils.toFiniteNumber(maxDownloadRate) + length: utils$1.toFiniteNumber(responseLength), + maxRate: utils$1.toFiniteNumber(maxDownloadRate) }); onDownloadProgress && transformStream.on('progress', progress => { @@ -35372,7 +35585,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { delete res.headers['content-encoding']; } - switch (res.headers['content-encoding']) { + switch ((res.headers['content-encoding'] || '').toLowerCase()) { /*eslint default-case:0*/ case 'gzip': case 'x-gzip': @@ -35401,7 +35614,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { } } - responseStream = streams.length > 1 ? stream__default["default"].pipeline(streams, utils.noop) : streams[0]; + responseStream = streams.length > 1 ? stream__default["default"].pipeline(streams, utils$1.noop) : streams[0]; const offListeners = stream__default["default"].finished(responseStream, () => { offListeners(); @@ -35463,12 +35676,12 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { if (responseType !== 'arraybuffer') { responseData = responseData.toString(responseEncoding); if (!responseEncoding || responseEncoding === 'utf8') { - responseData = utils.stripBOM(responseData); + responseData = utils$1.stripBOM(responseData); } } response.data = responseData; } catch (err) { - reject(AxiosError.from(err, null, config, response.request, response)); + return reject(AxiosError.from(err, null, config, response.request, response)); } settle(resolve, reject, response); }); @@ -35505,7 +35718,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types. const timeout = parseInt(config.timeout, 10); - if (isNaN(timeout)) { + if (Number.isNaN(timeout)) { reject(new AxiosError( 'error trying to parse `config.timeout` to int', AxiosError.ERR_BAD_OPTION_VALUE, @@ -35540,7 +35753,7 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { // Send the request - if (utils.isStream(data)) { + if (utils$1.isStream(data)) { let ended = false; let errored = false; @@ -35566,55 +35779,46 @@ const httpAdapter = isHttpAdapterSupported && function httpAdapter(config) { }); }; -const cookies = platform.isStandardBrowserEnv ? +const cookies = platform.hasStandardBrowserEnv ? -// Standard browser envs support document.cookie - (function standardBrowserEnv() { - return { - write: function write(name, value, expires, path, domain, secure) { - const cookie = []; - cookie.push(name + '=' + encodeURIComponent(value)); + // Standard browser envs support document.cookie + { + write(name, value, expires, path, domain, secure) { + const cookie = [name + '=' + encodeURIComponent(value)]; - if (utils.isNumber(expires)) { - cookie.push('expires=' + new Date(expires).toGMTString()); - } + utils$1.isNumber(expires) && cookie.push('expires=' + new Date(expires).toGMTString()); - if (utils.isString(path)) { - cookie.push('path=' + path); - } + utils$1.isString(path) && cookie.push('path=' + path); - if (utils.isString(domain)) { - cookie.push('domain=' + domain); - } + utils$1.isString(domain) && cookie.push('domain=' + domain); - if (secure === true) { - cookie.push('secure'); - } + secure === true && cookie.push('secure'); - document.cookie = cookie.join('; '); - }, + document.cookie = cookie.join('; '); + }, - read: function read(name) { - const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); - return (match ? decodeURIComponent(match[3]) : null); - }, + read(name) { + const match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); + return (match ? decodeURIComponent(match[3]) : null); + }, - remove: function remove(name) { - this.write(name, '', Date.now() - 86400000); - } - }; - })() : + remove(name) { + this.write(name, '', Date.now() - 86400000); + } + } -// Non standard browser env (web workers, react-native) lack needed support. - (function nonStandardBrowserEnv() { - return { - write: function write() {}, - read: function read() { return null; }, - remove: function remove() {} - }; - })(); + : -const isURLSameOrigin = platform.isStandardBrowserEnv ? + // Non-standard browser env (web workers, react-native) lack needed support. + { + write() {}, + read() { + return null; + }, + remove() {} + }; + +const isURLSameOrigin = platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test // whether the request URL is of the same origin as current location. @@ -35624,7 +35828,7 @@ const isURLSameOrigin = platform.isStandardBrowserEnv ? let originURL; /** - * Parse a URL to discover it's components + * Parse a URL to discover its components * * @param {String} url The URL to be parsed * @returns {Object} @@ -35664,7 +35868,7 @@ const isURLSameOrigin = platform.isStandardBrowserEnv ? * @returns {boolean} True if URL shares the same origin, otherwise false */ return function isURLSameOrigin(requestURL) { - const parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; + const parsed = (utils$1.isString(requestURL)) ? resolveURL(requestURL) : requestURL; return (parsed.protocol === originURL.protocol && parsed.host === originURL.host); }; @@ -35712,7 +35916,7 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { return new Promise(function dispatchXhrRequest(resolve, reject) { let requestData = config.data; const requestHeaders = AxiosHeaders$1.from(config.headers).normalize(); - const responseType = config.responseType; + let {responseType, withXSRFToken} = config; let onCanceled; function done() { if (config.cancelToken) { @@ -35724,11 +35928,15 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { } } - if (utils.isFormData(requestData)) { - if (platform.isStandardBrowserEnv || platform.isStandardBrowserWebWorkerEnv) { + let contentType; + + if (utils$1.isFormData(requestData)) { + if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) { requestHeaders.setContentType(false); // Let the browser set it - } else { - requestHeaders.setContentType('multipart/form-data;', false); // mobile/desktop app frameworks + } else if ((contentType = requestHeaders.getContentType()) !== false) { + // fix semicolon duplication issue for ReactNative FormData implementation + const [type, ...tokens] = contentType ? contentType.split(';').map(token => token.trim()).filter(Boolean) : []; + requestHeaders.setContentType([type || 'multipart/form-data', ...tokens].join('; ')); } } @@ -35844,13 +36052,16 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { // Add xsrf header // This is only done if running in a standard browser environment. // Specifically not if we're in a web worker, or react-native. - if (platform.isStandardBrowserEnv) { - // Add xsrf header - const xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) - && config.xsrfCookieName && cookies.read(config.xsrfCookieName); + if(platform.hasStandardBrowserEnv) { + withXSRFToken && utils$1.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(config)); - if (xsrfValue) { - requestHeaders.set(config.xsrfHeaderName, xsrfValue); + if (withXSRFToken || (withXSRFToken !== false && isURLSameOrigin(fullPath))) { + // Add xsrf header + const xsrfValue = config.xsrfHeaderName && config.xsrfCookieName && cookies.read(config.xsrfCookieName); + + if (xsrfValue) { + requestHeaders.set(config.xsrfHeaderName, xsrfValue); + } } } @@ -35859,13 +36070,13 @@ const xhrAdapter = isXHRAdapterSupported && function (config) { // Add headers to the request if ('setRequestHeader' in request) { - utils.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { + utils$1.forEach(requestHeaders.toJSON(), function setRequestHeader(val, key) { request.setRequestHeader(key, val); }); } // Add withCredentials to request if needed - if (!utils.isUndefined(config.withCredentials)) { + if (!utils$1.isUndefined(config.withCredentials)) { request.withCredentials = !!config.withCredentials; } @@ -35920,8 +36131,8 @@ const knownAdapters = { xhr: xhrAdapter }; -utils.forEach(knownAdapters, (fn, value) => { - if(fn) { +utils$1.forEach(knownAdapters, (fn, value) => { + if (fn) { try { Object.defineProperty(fn, 'name', {value}); } catch (e) { @@ -35931,38 +36142,56 @@ utils.forEach(knownAdapters, (fn, value) => { } }); +const renderReason = (reason) => `- ${reason}`; + +const isResolvedHandle = (adapter) => utils$1.isFunction(adapter) || adapter === null || adapter === false; + const adapters = { getAdapter: (adapters) => { - adapters = utils.isArray(adapters) ? adapters : [adapters]; + adapters = utils$1.isArray(adapters) ? adapters : [adapters]; const {length} = adapters; let nameOrAdapter; let adapter; + const rejectedReasons = {}; + for (let i = 0; i < length; i++) { nameOrAdapter = adapters[i]; - if((adapter = utils.isString(nameOrAdapter) ? knownAdapters[nameOrAdapter.toLowerCase()] : nameOrAdapter)) { + let id; + + adapter = nameOrAdapter; + + if (!isResolvedHandle(nameOrAdapter)) { + adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; + + if (adapter === undefined) { + throw new AxiosError(`Unknown adapter '${id}'`); + } + } + + if (adapter) { break; } + + rejectedReasons[id || '#' + i] = adapter; } if (!adapter) { - if (adapter === false) { - throw new AxiosError( - `Adapter ${nameOrAdapter} is not supported by the environment`, - 'ERR_NOT_SUPPORT' + + const reasons = Object.entries(rejectedReasons) + .map(([id, state]) => `adapter ${id} ` + + (state === false ? 'is not supported by the environment' : 'is not available in the build') ); - } - throw new Error( - utils.hasOwnProp(knownAdapters, nameOrAdapter) ? - `Adapter '${nameOrAdapter}' is not available in the build` : - `Unknown adapter '${nameOrAdapter}'` - ); - } + let s = length ? + (reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0])) : + 'as no adapter specified'; - if (!utils.isFunction(adapter)) { - throw new TypeError('adapter is not a function'); + throw new AxiosError( + `There is no suitable adapter to dispatch the request ` + s, + 'ERR_NOT_SUPPORT' + ); } return adapter; @@ -36060,11 +36289,11 @@ function mergeConfig(config1, config2) { const config = {}; function getMergedValue(target, source, caseless) { - if (utils.isPlainObject(target) && utils.isPlainObject(source)) { - return utils.merge.call({caseless}, target, source); - } else if (utils.isPlainObject(source)) { - return utils.merge({}, source); - } else if (utils.isArray(source)) { + if (utils$1.isPlainObject(target) && utils$1.isPlainObject(source)) { + return utils$1.merge.call({caseless}, target, source); + } else if (utils$1.isPlainObject(source)) { + return utils$1.merge({}, source); + } else if (utils$1.isArray(source)) { return source.slice(); } return source; @@ -36072,25 +36301,25 @@ function mergeConfig(config1, config2) { // eslint-disable-next-line consistent-return function mergeDeepProperties(a, b, caseless) { - if (!utils.isUndefined(b)) { + if (!utils$1.isUndefined(b)) { return getMergedValue(a, b, caseless); - } else if (!utils.isUndefined(a)) { + } else if (!utils$1.isUndefined(a)) { return getMergedValue(undefined, a, caseless); } } // eslint-disable-next-line consistent-return function valueFromConfig2(a, b) { - if (!utils.isUndefined(b)) { + if (!utils$1.isUndefined(b)) { return getMergedValue(undefined, b); } } // eslint-disable-next-line consistent-return function defaultToConfig2(a, b) { - if (!utils.isUndefined(b)) { + if (!utils$1.isUndefined(b)) { return getMergedValue(undefined, b); - } else if (!utils.isUndefined(a)) { + } else if (!utils$1.isUndefined(a)) { return getMergedValue(undefined, a); } } @@ -36115,6 +36344,7 @@ function mergeConfig(config1, config2) { timeout: defaultToConfig2, timeoutMessage: defaultToConfig2, withCredentials: defaultToConfig2, + withXSRFToken: defaultToConfig2, adapter: defaultToConfig2, responseType: defaultToConfig2, xsrfCookieName: defaultToConfig2, @@ -36135,10 +36365,10 @@ function mergeConfig(config1, config2) { headers: (a, b) => mergeDeepProperties(headersToObject(a), headersToObject(b), true) }; - utils.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) { + utils$1.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) { const merge = mergeMap[prop] || mergeDeepProperties; const configValue = merge(config1[prop], config2[prop], prop); - (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); + (utils$1.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); }); return config; @@ -36280,7 +36510,7 @@ class Axios { } if (paramsSerializer != null) { - if (utils.isFunction(paramsSerializer)) { + if (utils$1.isFunction(paramsSerializer)) { config.paramsSerializer = { serialize: paramsSerializer }; @@ -36295,15 +36525,13 @@ class Axios { // Set config.method config.method = (config.method || this.defaults.method || 'get').toLowerCase(); - let contextHeaders; - // Flatten headers - contextHeaders = headers && utils.merge( + let contextHeaders = headers && utils$1.merge( headers.common, headers[config.method] ); - contextHeaders && utils.forEach( + headers && utils$1.forEach( ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], (method) => { delete headers[method]; @@ -36390,7 +36618,7 @@ class Axios { } // Provide aliases for supported request methods -utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { +utils$1.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { /*eslint func-names:0*/ Axios.prototype[method] = function(url, config) { return this.request(mergeConfig(config || {}, { @@ -36401,7 +36629,7 @@ utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData }; }); -utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { +utils$1.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { /*eslint func-names:0*/ function generateHTTPMethod(isForm) { @@ -36577,7 +36805,7 @@ function spread(callback) { * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false */ function isAxiosError(payload) { - return utils.isObject(payload) && (payload.isAxiosError === true); + return utils$1.isObject(payload) && (payload.isAxiosError === true); } const HttpStatusCode = { @@ -36664,10 +36892,10 @@ function createInstance(defaultConfig) { const instance = bind(Axios$1.prototype.request, context); // Copy axios.prototype to instance - utils.extend(instance, Axios$1.prototype, context, {allOwnKeys: true}); + utils$1.extend(instance, Axios$1.prototype, context, {allOwnKeys: true}); // Copy context to instance - utils.extend(instance, context, null, {allOwnKeys: true}); + utils$1.extend(instance, context, null, {allOwnKeys: true}); // Factory for creating new instances instance.create = function create(instanceConfig) { @@ -36711,7 +36939,9 @@ axios.mergeConfig = mergeConfig; axios.AxiosHeaders = AxiosHeaders$1; -axios.formToJSON = thing => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing); +axios.formToJSON = thing => formDataToJSON(utils$1.isHTMLForm(thing) ? new FormData(thing) : thing); + +axios.getAdapter = adapters.getAdapter; axios.HttpStatusCode = HttpStatusCode$1; @@ -36794,31 +37024,30 @@ const _ = __nccwpck_require__(250); const { getAllTransformations, getAllLibraries, - createTransformer, + createTransformation, createLibrary, - updateTransformer, + updateTransformation, updateLibrary, testTransformationAndLibrary, publish, } = __nccwpck_require__(9620); const testOutputDir = "./test-outputs"; -const uploadTestArtifact = core.getInput("uploadTestArtifact") || false; +const uploadTestArtifact = + core.getInput("uploadTestArtifact").toLowerCase() == "true"; const metaFilePath = core.getInput("metaPath"); -const serverList = { - transformations: [], - libraries: [], -}; - -const transformationNameToId = {}; -const libraryNameToId = {}; - const testOnly = process.env.TEST_ONLY !== "false"; const commitId = process.env.GITHUB_SHA || ""; -function getTransformationsAndLibrariesFromLocal(transformations, libraries) { - core.info("metaFilePath: " + metaFilePath); +// Load transformations and libraries from a local meta file. +function getTransformationsAndLibrariesFromLocal() { + core.info( + `Loading transformations and libraries from the meta file: ${metaFilePath}` + ); + const transformations = []; + const libraries = []; + let meta = JSON.parse(fs.readFileSync(metaFilePath, "utf-8")); if (meta.transformations) { transformations.push(...meta.transformations); @@ -36826,242 +37055,333 @@ function getTransformationsAndLibrariesFromLocal(transformations, libraries) { if (meta.libraries) { libraries.push(...meta.libraries); } + return { transformations, libraries }; } -function buildNametoIdMap(objectArr, type) { - if (type == "tr") { - objectArr.map((tr) => { - transformationNameToId[tr.name] = tr.id; - }); - } else { - objectArr.map((lib) => { - libraryNameToId[lib.name] = lib.id; - }); - } +function buildNameToIdMap(arr) { + return arr.reduce((map, entry) => { + map[entry.name] = entry.id; + return map; + }, {}); } -async function init() { - let res = await getAllTransformations(); - serverList.transformations = res.data - ? JSON.parse(JSON.stringify(res.data.transformations)) +// Fetch transformation and libraries. +async function loadTransformationsAndLibraries() { + let workspaceTransformations = []; + let workspaceLibraries = []; + + const transformationsResponse = await getAllTransformations(); + workspaceTransformations = transformationsResponse.data + ? JSON.parse(JSON.stringify(transformationsResponse.data.transformations)) : []; - res = await getAllLibraries(); - serverList.libraries = res.data - ? JSON.parse(JSON.stringify(res.data.libraries)) + + const librariesResponse = await getAllLibraries(); + workspaceLibraries = librariesResponse.data + ? JSON.parse(JSON.stringify(librariesResponse.data.libraries)) : []; - buildNametoIdMap(serverList.transformations, "tr"); - buildNametoIdMap(serverList.libraries, "lib"); + return { workspaceTransformations, workspaceLibraries }; } -async function testAndPublish() { +// Create or update transformations +async function upsertTransformations(transformations, transformationNameToId) { + core.info(`Upserting transformations`); const transformationDict = {}; - const libraryDict = {}; - try { - core.info("Initilaizing..."); - let transformations = []; - let libraries = []; - getTransformationsAndLibrariesFromLocal(transformations, libraries); - await init(); - - core.info("list of transformations and libraries successfully fetched"); - - for (let i = 0; i < transformations.length; i++) { - let tr = transformations[i]; - let code = fs.readFileSync(tr.file, "utf-8"); - let res; - if (transformationNameToId[tr.name]) { - // update existing transformer and get a new versionId - let id = transformationNameToId[tr.name]; - res = await updateTransformer(id, tr.description, code, tr.language); - core.info(`updated transformation: ${tr.name}`); - } else { - // create new transformer - res = await createTransformer( - tr.name, - tr.description, - code, - tr.language - ); - core.info(`created transformation: ${tr.name}`); - } - transformationDict[res.data.versionId] = { ...tr, id: res.data.id }; + for (const tr of transformations) { + const code = fs.readFileSync(tr.file, "utf-8"); + let res; + if (transformationNameToId[tr.name]) { + // update existing transformer and get a new versionId + core.info(`Updating transformation: ${tr.name}`); + const id = transformationNameToId[tr.name]; + res = await updateTransformation( + id, + tr.name, + tr.description, + code, + tr.language + ); + } else { + core.info(`Creating transformation: ${tr.name}`); + // create new transformer + res = await createTransformation( + tr.name, + tr.description, + code, + tr.language + ); } - core.info("Transformations create/update done!"); + transformationDict[res.data.versionId] = { ...tr, id: res.data.id }; + } - for (let i = 0; i < libraries.length; i++) { - let lib = libraries[i]; - let code = fs.readFileSync(lib.file, "utf-8"); - let res; - if (libraryNameToId[lib.name]) { - // update library and get a new versionId - let id = libraryNameToId[lib.name]; - res = await updateLibrary(id, lib.description, code, lib.language); - core.info(`updated library: ${lib.name}`); - } else { - // create a new library - res = await createLibrary( - lib.name, - lib.description, - code, - lib.language - ); - core.info(`created library: ${lib.name}`); - } - libraryDict[res.data.versionId] = { ...lib, id: res.data.id }; + return transformationDict; +} + +// Create or update a library. +async function upsertLibraries(libraries, libraryNameToId) { + core.info(`Upserting libraries`); + const libraryDict = {}; + for (const lib of libraries) { + const code = fs.readFileSync(lib.file, "utf-8"); + let res; + if (libraryNameToId[lib.name]) { + // update library and get a new versionId + core.info(`Updating library: ${lib.name}`); + const id = libraryNameToId[lib.name]; + res = await updateLibrary(id, lib.description, code, lib.language); + } else { + // create a new library + core.info(`Creating library: ${lib.name}`); + res = await createLibrary(lib.name, lib.description, code, lib.language); } - core.info("Libraries create/update done!"); + libraryDict[res.data.versionId] = { ...lib, id: res.data.id }; + } + return libraryDict; +} - let transformationTest = []; - let librariesTest = []; +// Build the test suite. +async function buildTestSuite(transformationDict, libraryDict) { + core.info("Building test suite"); + const transformationTest = [], + librariesTest = []; - core.info("Building test suite..."); - for (let i = 0; i < Object.keys(transformationDict).length; i++) { - let trVersionId = Object.keys(transformationDict)[i]; - let testInputPath = - transformationDict[trVersionId]["test-input-file"] || ""; - let testInput = testInputPath - ? JSON.parse(fs.readFileSync(testInputPath)) - : ""; - if (testInput) { - transformationTest.push({ versionId: trVersionId, testInput }); - } else { - core.info( - `No test input provided. Testing ${transformationDict[trVersionId].name} with default payload` - ); - transformationTest.push({ versionId: trVersionId }); - } + for (const trVersionId of Object.keys(transformationDict)) { + const testInputPath = + transformationDict[trVersionId]["test-input-file"] || ""; + const testInput = testInputPath + ? JSON.parse(fs.readFileSync(testInputPath)) + : ""; + if (testInput) { + transformationTest.push({ versionId: trVersionId, testInput }); + } else { + core.info( + `No test input provided. Testing ${transformationDict[trVersionId].name} with default payload` + ); + transformationTest.push({ versionId: trVersionId }); } + } - for (let i = 0; i < Object.keys(libraryDict).length; i++) { - librariesTest.push({ versionId: Object.keys(libraryDict)[i] }); - } + for (const versionId of Object.keys(libraryDict)) { + librariesTest.push({ versionId }); + } - core.info( - `final transformation versions to be tested: - ${JSON.stringify(transformationTest)}` - ); - core.info( - `final library versions to be tested: ${JSON.stringify(librariesTest)}` - ); + core.info( + `Final transformation versions to be tested: + ${JSON.stringify(transformationTest)}` + ); + core.info( + `Final library versions to be tested: ${JSON.stringify(librariesTest)}` + ); + return { transformationTest, librariesTest }; +} + +// Run the test suite. +async function runTestSuite(transformationTest, librariesTest) { + core.info("Running test suite for transformations and libraries"); + + let res = await testTransformationAndLibrary( + transformationTest, + librariesTest + ); - core.info("Running test..."); + logResult(res.data.result); - let res = await testTransformationAndLibrary( - transformationTest, - librariesTest + if (res.data.result.failedTestResults.length > 0) { + throw new Error( + "Failures occured while running tests against input events" ); - core.info(`Test api output: ${JSON.stringify(res.data)}`); + } - if (res.data.result.failedTestResults.length > 0) { - core.info( - `Failed tests: ${JSON.stringify( - res.data.result.failedTestResults, - null, - 2 - )}` - ); - throw new Error( - "failures occured while running tests against input events" - ); - } + return res; +} - let successResults = res.data.result.successTestResults; +// Compare the API output with the actual output. +async function compareOutput(successResults, transformationDict) { + core.info("Comparing actual output with expected output"); + const outputMismatchResults = []; + const testOutputFiles = []; + for (const successResult of successResults) { + const transformerVersionID = successResult.transformerVersionID; - let outputMismatchResults = []; - let testOutputFiles = []; if (!fs.existsSync(testOutputDir)) { fs.mkdirSync(testOutputDir); } + if (!transformationDict.hasOwnProperty(transformerVersionID)) { + core.warn( + `Transformer with version id: ${transformerVersionID} not found.` + ); + continue; + } - core.info("Comparing api output with expected output..."); - for (let i = 0; i < successResults.length; i++) { - let transformerVersionID = successResults[i].transformerVersionID; - if (!transformationDict.hasOwnProperty(transformerVersionID)) { - continue; - } + const actualOutput = successResult.result.output.transformedEvents; + const transformationName = transformationDict[transformerVersionID].name; + const transformationHandleName = _.camelCase(transformationName); + + fs.writeFileSync( + `${testOutputDir}/${transformationHandleName}_output.json`, + JSON.stringify(actualOutput, null, 2) + ); + testOutputFiles.push( + `${testOutputDir}/${transformationHandleName}_output.json` + ); - const apiOutput = successResults[i].result.output.transformedEvents; - const transformationName = transformationDict[transformerVersionID].name; - const transformationHandleName = _.camelCase(transformationName); + if ( + !transformationDict[transformerVersionID].hasOwnProperty( + "expected-output" + ) + ) { + continue; + } + + const expectedOutputfile = + transformationDict[transformerVersionID]["expected-output"]; + const expectedOutput = expectedOutputfile + ? JSON.parse(fs.readFileSync(expectedOutputfile)) + : ""; + + if (expectedOutput == "") { + continue; + } + + if (!isEqual(expectedOutput, actualOutput)) { + core.info( + `Test output do not match for transformation: ${transformationName}` + ); + outputMismatchResults.push( + `Test output do not match for transformation: ${transformationName}` + ); fs.writeFileSync( - `${testOutputDir}/${transformationHandleName}_output.json`, - JSON.stringify(apiOutput, null, 2) + `${testOutputDir}/${transformationHandleName}_diff.json`, + JSON.stringify(detailedDiff(expectedOutput, actualOutput), null, 2) ); + testOutputFiles.push( - `${testOutputDir}/${transformationHandleName}_output.json` + `${testOutputDir}/${transformationHandleName}_diff.json` ); + } + } + return { outputMismatchResults, testOutputFiles }; +} - if ( - !transformationDict[transformerVersionID].hasOwnProperty( - "expected-output" - ) - ) { - continue; - } +// Upload the test results to an artifact store. +async function uploadTestArtifacts(testOutputFiles) { + core.info(`Uploading test artifacts`); + // upload artifact - let expectedOutputfile = - transformationDict[transformerVersionID]["expected-output"]; - let expectedOutput = expectedOutputfile - ? JSON.parse(fs.readFileSync(expectedOutputfile)) - : ""; + core.info("Uploading test api output"); + const artifactClientResponse = await artifactClient.uploadArtifact( + "transformer-test-results", + testOutputFiles, + "." + ); - if (expectedOutput == "") { - continue; - } + if (artifactClientResponse.failedItems.length > 0) { + throw new Error( + `Artifacts upload failed, items: ${JSON.stringify(failedItems)}` + ); + } +} - if (!isEqual(expectedOutput, apiOutput)) { - core.info( - `Test output do not match for transformation: ${transformationName}` - ); - outputMismatchResults.push( - `Test output do not match for transformation: ${transformationName}` - ); +// Publish the transformations and libraries. +async function publishTransformation( + transformationTest, + librariesTest, + commitId +) { + core.info(`Publishing transformations and libraries`); + // publish + res = await publish(transformationTest, librariesTest, commitId); +} + +function colorize(message, color) { + const colors = { + reset: "\x1b[0m", + red: "\x1b[31m", + green: "\x1b[32m", + yellow: "\x1b[33m", + blue: "\x1b[34m", + magenta: "\x1b[35m", + cyan: "\x1b[36m", + white: "\x1b[37m", + }; - fs.writeFileSync( - `${testOutputDir}/${transformationHandleName}_diff.json`, - JSON.stringify(detailedDiff(expectedOutput, apiOutput), null, 2) - ); + return `${colors[color]}${message}${colors.reset}`; +} - testOutputFiles.push( - `${testOutputDir}/${transformationHandleName}_diff.json` - ); - } +// Log failed tests +function logResult(result) { + core.info( + colorize( + `\nTotal tests ${ + result.successTestResults.length + result.failedTestResults.length + }, ${result.successTestResults.length} passed and ${ + result.failedTestResults.length + } failed\n`, + "yellow" + ) + ); + if (result.failedTestResults.length > 0) { + core.info(colorize("\nFailed Tests:\n", "yellow")); + for (const test of result.failedTestResults) { + core.info(colorize(` ID: ${test.id}`, "red")); + core.info(colorize(` Name: ${test.name}`, "red")); + core.info(colorize(` Error: ${JSON.stringify(test.result)}\n`, "red")); + core.info("\n" + "=".repeat(40) + "\n"); // Add a line of equal signs between logs } + } +} - // upload artifact - if (uploadTestArtifact === "true") { - core.info("Uploading test api output..."); - await artifactClient.uploadArtifact( - "transformer-test-results", - testOutputFiles, - "." - ); - } +async function testAndPublish() { + core.info("Initializing"); - if (outputMismatchResults.length > 0) { - throw new Error(outputMismatchResults.join(", ")); - } + const { transformations, libraries } = + getTransformationsAndLibrariesFromLocal(); + const { workspaceTransformations, workspaceLibraries } = + await loadTransformationsAndLibraries(); - // test passed - core.info("Test Passed!!!"); + const transformationNameToId = buildNameToIdMap(workspaceTransformations); + const libraryNameToId = buildNameToIdMap(workspaceLibraries); - // publish - if (!testOnly) { - res = await publish(transformationTest, librariesTest, commitId); - core.info(`Publish result: ${JSON.stringify(res.data)}`); - } - } catch (err) { - if (err.response) { - core.error(err.response.data); - core.error(err.response.status); - } - core.setFailed(err); + core.info("List of transformations and libraries successfully fetched"); + + const transformationDict = await upsertTransformations( + transformations, + transformationNameToId + ); + + const libraryDict = await upsertLibraries(libraries, libraryNameToId); + + const { transformationTest, librariesTest } = await buildTestSuite( + transformationDict, + libraryDict + ); + + const testSuiteResult = ( + await runTestSuite(transformationTest, librariesTest) + ).data.result; + + const { outputMismatchResults, testOutputFiles } = await compareOutput( + testSuiteResult.successTestResults, + transformationDict + ); + + if (uploadTestArtifact) { + await uploadTestArtifacts(testOutputFiles); + } + + if (outputMismatchResults.length > 0) { + throw new Error(outputMismatchResults.join(", ")); + } + + core.info("Test Passed!!!"); + if (!testOnly) { + await publishTransformation(transformationTest, librariesTest, commitId); } } +// Start the testing and publishing process. testAndPublish(); })(); diff --git a/package.json b/package.json index 7d1d92e..db3a5f0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "src/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "npx ncc build src/index.js -o dist" + "build": "ncc build --no-cache src/index.js -o dist" }, "author": "", "license": "ISC", @@ -18,8 +18,5 @@ }, "devDependencies": { "@vercel/ncc": "^0.36.1" - }, - "engines": { - "npm": "^9.6.7" } }