From a5e8429dc5f8b0eaa52d26899a6d7f575d018f27 Mon Sep 17 00:00:00 2001 From: Joe DeStefano Date: Thu, 24 Aug 2023 11:07:20 -0700 Subject: [PATCH] feat(artifacts): Add support for trigger artifacts --- README.md | 25 ++++--- __tests__/main.test.ts | 131 +++++++++++++++++++++++++++++++++++- package.json | 1 + src/main.ts | 57 ++++++++++++++-- yarn.lock | 147 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 341 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index e13d986..fd86bb3 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ steps: - name: Spinnaker uses: ExpediaGroup/spinnaker-pipeline-trigger@v1 with: + github_token: ${{ secrets.GITHUB_TOKEN }} topic_arn: ${{ secrets.SPINNAKER_TOPIC_ARN }} ``` @@ -38,6 +39,8 @@ The action sends the following information in the payload: * githubEventName: The name of the webhook event that triggered the workflow. * githubActor: The name of the person or app that initiated the workflow. For example, octocat. * githubAction: Always set to true when GitHub Actions is running the workflow. You can use this variable to differentiate when tests are being run locally or by GitHub Actions. +* githubApiUrl: The base URL for the REST API endpoint for your GitHub instance. For example, `https://api.github.com`. This is used to construct Artifact objects for each of the modified or added files when present. +* modifiedFiles: A list of all the modified or added files in the commmit that triggered the workflow. For example, `["README.md", ".github/workflows/release.yaml"]`. If the `github_token` parameter is missing from the step config, or if the list of modified files is so large the SNS message body would exceed 256 KB, this value is set to an empty list instead. ### Additional Parameters @@ -48,6 +51,7 @@ steps: - name: Spinnaker uses: ExpediaGroup/spinnaker-pipeline-trigger@v1 with: + github_token: ${{ secrets.GITHUB_TOKEN }} topic_arn: ${{ secrets.SPINNAKER_TOPIC_ARN }} parameters: | parameter1: value1 @@ -67,6 +71,7 @@ steps: - name: Spinnaker uses: ExpediaGroup/spinnaker-pipeline-trigger@v1 with: + github_token: ${{ secrets.GITHUB_TOKEN }} topic_arn: ${{ secrets.SPINNAKER_TOPIC_ARN }} parameters: | parameter1: value1 @@ -89,21 +94,21 @@ Follow Spinnaker's directions for [setting up a topic and queue](https://spinnak * Do not set up the S3 notification * `messageFormat` should be `CUSTOM` -* Include the template below with the `echo` portion of the config. +* Include the template below with the `echo` portion of the config to receive GitHub file artifacts on the triggered pipelines. If you are running Echo in sharded mode, this config should be included in the scheduler instances. Sample message format based on the default parameters being sent: - ```json [ + {% for item in modifiedFiles %} { - "reference": "{{ reference }}", - "repository": "{{ repository }}", - "commit": "{{ commit }}", - "ref": "{{ ref }}", - "githubEventName": "{{ githubEventName }}", - "githubActor": "{{ githubActor }}", - "githubAction": "{{ githubAction }}" - } + "customKind": false, + "reference": "{{ githubApiUrl }}/repos/{{ repository }}/contents/{{ item }}", + "metadata": {}, + "name": "{{ item }}", + "type": "github/file", + "version": "{{ commit }}" + }{% if not loop.last %},{% endif %} + {% endfor %} ] ``` diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 9c3ea54..09be77c 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -14,11 +14,33 @@ See the License for the specific language governing permissions and limitations under the License. */ +const githubContext = { + repo: { + owner: 'Org', + repo: 'actions-test-trigger' + }, + sha: 'long-sha' +} +const mockedGetCommit = jest.fn() +const mockOctokit = { + rest: { + repos: { + getCommit: mockedGetCommit + } + } +} + import { SNSClient, PublishCommand } from '@aws-sdk/client-sns' import { run } from '../src/main' // Capture environment variables before running tests const cleanEnv = process.env +jest.mock('@actions/github', () => { + return { + context: githubContext, + getOctokit: () => mockOctokit + } +}) jest.mock('@aws-sdk/client-sns') const mockedSend = jest.fn().mockReturnValue({ MessageId: '1' }) @@ -32,6 +54,7 @@ describe('Publish', () => { process.env.GITHUB_REPOSITORY = 'Org/actions-test-trigger' process.env.GITHUB_SHA = 'long-sha' process.env.GITHUB_REF = 'main' + process.env.GITHUB_API_URL = 'https://api.github.com' SNSClient.prototype.send = mockedSend }) @@ -41,7 +64,7 @@ describe('Publish', () => { const input = { Message: - '{"repository":"Org/actions-test-trigger","commit":"long-sha","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":""}', + '{"repository":"Org/actions-test-trigger","commit":"long-sha","githubApiUrl":"https://api.github.com","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":"","modifiedFiles":[]}', TopicArn: 'arn:aws:sns:us-west-2:123456789123:spinnaker-github-actions' } @@ -52,6 +75,7 @@ describe('Publish', () => { expect(SNSClient).toBeCalledWith({ region }) expect(PublishCommand).toBeCalledWith(input) expect(mockedSend).toBeCalledTimes(1) + expect(mockedGetCommit).not.toHaveBeenCalled() }) test('No REF passed in', async () => { @@ -61,7 +85,7 @@ describe('Publish', () => { const input = { Message: - '{"repository":"Org/actions-test-trigger","commit":"long-sha","ref":"","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":""}', + '{"repository":"Org/actions-test-trigger","commit":"long-sha","githubApiUrl":"https://api.github.com","ref":"","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":"","modifiedFiles":[]}', TopicArn: 'arn:aws:sns:us-west-2:123456789123:spinnaker-github-actions' } @@ -72,6 +96,7 @@ describe('Publish', () => { expect(SNSClient).toBeCalledWith({ region }) expect(PublishCommand).toBeCalledWith(input) expect(mockedSend).toBeCalledTimes(1) + expect(mockedGetCommit).not.toHaveBeenCalled() }) test('With Parameters and Message Attributes', async () => { // Arrange @@ -81,7 +106,7 @@ describe('Publish', () => { const input = { Message: - '{"repository":"Org/actions-test-trigger","commit":"long-sha","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{"parameter1":"value1","parameter2":"value2"},"messageAttributes":"my-attribute"}', + '{"repository":"Org/actions-test-trigger","commit":"long-sha","githubApiUrl":"https://api.github.com","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{"parameter1":"value1","parameter2":"value2"},"messageAttributes":"my-attribute","modifiedFiles":[]}', TopicArn: 'arn:aws:sns:us-west-2:123456789123:spinnaker-github-actions' } @@ -92,6 +117,105 @@ describe('Publish', () => { expect(SNSClient).toBeCalledWith({ region }) expect(PublishCommand).toBeCalledWith(input) expect(mockedSend).toBeCalledTimes(1) + expect(mockedGetCommit).not.toHaveBeenCalled() + }) + + describe('when github_token is present', () => { + beforeEach(() => { + process.env.INPUT_GITHUB_TOKEN = 'token' + }) + + test('when commit response has no files it returns an empty list for modifiedFiles', async () => { + // Arrange + const region = 'us-west-2' + + const input = { + Message: + '{"repository":"Org/actions-test-trigger","commit":"long-sha","githubApiUrl":"https://api.github.com","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":"","modifiedFiles":[]}', + TopicArn: 'arn:aws:sns:us-west-2:123456789123:spinnaker-github-actions' + } + mockedGetCommit.mockResolvedValueOnce({ + data: {} + }) + + // Act + await run() + + // Assert + expect(SNSClient).toBeCalledWith({ region }) + expect(PublishCommand).toBeCalledWith(input) + expect(mockedSend).toBeCalledTimes(1) + expect(mockedGetCommit).toBeCalledWith({ + owner: 'Org', + repo: 'actions-test-trigger', + ref: 'long-sha' + }) + }) + + test('it returns a list of modified and added files', async () => { + // Arrange + const region = 'us-west-2' + + const input = { + Message: + '{"repository":"Org/actions-test-trigger","commit":"long-sha","githubApiUrl":"https://api.github.com","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":"","modifiedFiles":["file1","file2","file4"]}', + TopicArn: 'arn:aws:sns:us-west-2:123456789123:spinnaker-github-actions' + } + mockedGetCommit.mockResolvedValueOnce({ + data: { + files: [ + { filename: 'file1', status: 'added' }, + { filename: 'file2', status: 'modified' }, + { filename: 'file3', status: 'removed' }, + { filename: 'file4', status: 'added' } + ] + } + }) + + // Act + await run() + + // Assert + expect(SNSClient).toBeCalledWith({ region }) + expect(PublishCommand).toBeCalledWith(input) + expect(mockedSend).toBeCalledTimes(1) + expect(mockedGetCommit).toBeCalledWith({ + owner: 'Org', + repo: 'actions-test-trigger', + ref: 'long-sha' + }) + }) + + test('when the message is too large it returns an empty list for modifiedFiles', async () => { + // Arrange + const region = 'us-west-2' + + const input = { + Message: + '{"repository":"Org/actions-test-trigger","commit":"long-sha","githubApiUrl":"https://api.github.com","ref":"main","githubEventName":"","githubActor":"","githubAction":"","parameters":{},"messageAttributes":"","modifiedFiles":[]}', + TopicArn: 'arn:aws:sns:us-west-2:123456789123:spinnaker-github-actions' + } + mockedGetCommit.mockResolvedValueOnce({ + data: { + files: Array.from({ length: 500000 }, (_value, index) => { + return { filename: `file${index}`, status: 'added' } + }) + } + }) + + // Act + await run() + + // Assert + expect(SNSClient).toBeCalledWith({ region }) + expect(PublishCommand).toBeCalledWith(input) + expect(mockedSend).toBeCalledTimes(1) + expect(mockedGetCommit).toBeCalledWith({ + owner: 'Org', + repo: 'actions-test-trigger', + ref: 'long-sha' + }) + }) }) }) @@ -112,5 +236,6 @@ describe('fail', () => { expect(SNSClient).not.toBeCalled() expect(PublishCommand).not.toBeCalled() expect(mockedSend).not.toBeCalled() + expect(mockedGetCommit).not.toHaveBeenCalled() }) }) diff --git a/package.json b/package.json index 4a22b86..7a05a72 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "license": "MIT", "dependencies": { "@actions/core": "1.10.0", + "@actions/github": "^5.1.1", "@aws-sdk/client-sns": "3.395.0", "@types/js-yaml": "^4.0.5", "@types/node": "20.5.3", diff --git a/src/main.ts b/src/main.ts index 3b2c3d5..c608603 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,6 +15,7 @@ limitations under the License. */ import * as core from '@actions/core' +import * as github from '@actions/github' import * as yaml from 'js-yaml' import { PublishCommand, @@ -23,6 +24,13 @@ import { SNSClient } from '@aws-sdk/client-sns' +const SNS_MESSAGE_SIZE_LIMIT_BYTES = 256000 + +interface GitHubFile { + filename: string + status: string +} + async function publish( message: object, topicArn: string, @@ -45,26 +53,67 @@ async function publish( return JSON.stringify(response.MessageId) } -function constructMessage(): object { +async function constructMessage(): Promise { const repository = process.env.GITHUB_REPOSITORY const commit = process.env.GITHUB_SHA + const githubApiUrl = process.env.GITHUB_API_URL const ref = process.env.GITHUB_REF || '' const githubAction = process.env.GITHUB_ACTION || '' const githubEventName = process.env.GITHUB_EVENT_NAME || '' const githubActor = process.env.GITHUB_ACTOR || '' const parameters = yaml.load(core.getInput('parameters')) || {} const messageAttributes = core.getInput('message_attributes') || '' + const modifiedFiles = await getModifiedFiles() - return { + const message = { repository, commit, + githubApiUrl, ref, githubEventName, githubActor, githubAction, parameters, - messageAttributes + messageAttributes, + modifiedFiles + } + + // SNS message size limit is 256 KB + if ( + Buffer.byteLength(JSON.stringify(message)) > SNS_MESSAGE_SIZE_LIMIT_BYTES + ) { + core.warning( + 'SNS message size limit exceeded, removing modifiedFiles from message' + ) + message.modifiedFiles = [] + } + + return message +} + +async function getModifiedFiles(): Promise { + const token = core.getInput('github_token') + if (!token) { + core.debug( + 'No github token provided, defaulting to empty list of modified files' + ) + return [] + } + const octokit = github.getOctokit(token) + const { data } = await octokit.rest.repos.getCommit({ + owner: github.context.repo.owner, + repo: github.context.repo.repo, + ref: github.context.sha + }) + if (!data.files) { + core.debug('No files found in getCommit response') + return [] } + const files = data.files + .filter((file: GitHubFile) => file.status !== 'removed') + .map((file: GitHubFile) => file.filename) + core.debug(`Found ${files.length} changed files`) + return files } export async function run(): Promise { @@ -77,7 +126,7 @@ export async function run(): Promise { if (!topicArn) { throw new Error('Topic ARN is required.') } - const message = constructMessage() + const message = await constructMessage() core.debug(JSON.stringify(message)) await publish(message, topicArn, region) } catch (error) { diff --git a/yarn.lock b/yarn.lock index a3956f8..a8b0e63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,16 @@ "@actions/http-client" "^2.0.1" uuid "^8.3.2" +"@actions/github@^5.1.1": + version "5.1.1" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@actions/github/-/github-5.1.1.tgz#40b9b9e1323a5efcf4ff7dadd33d8ea51651bbcb" + integrity sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g== + dependencies: + "@actions/http-client" "^2.0.1" + "@octokit/core" "^3.6.0" + "@octokit/plugin-paginate-rest" "^2.17.0" + "@octokit/plugin-rest-endpoint-methods" "^5.13.0" + "@actions/http-client@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" @@ -1271,6 +1281,92 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@octokit/auth-token@^2.4.4": + version "2.5.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" + integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== + dependencies: + "@octokit/types" "^6.0.3" + +"@octokit/core@^3.6.0": + version "3.6.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" + integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== + dependencies: + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.6.3" + "@octokit/request-error" "^2.0.5" + "@octokit/types" "^6.0.3" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + +"@octokit/endpoint@^6.0.1": + version "6.0.12" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" + integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA== + dependencies: + "@octokit/types" "^6.0.3" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^4.5.8": + version "4.8.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" + integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg== + dependencies: + "@octokit/request" "^5.6.0" + "@octokit/types" "^6.0.3" + universal-user-agent "^6.0.0" + +"@octokit/openapi-types@^12.11.0": + version "12.11.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" + integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== + +"@octokit/plugin-paginate-rest@^2.17.0": + version "2.21.3" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz#7f12532797775640dbb8224da577da7dc210c87e" + integrity sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw== + dependencies: + "@octokit/types" "^6.40.0" + +"@octokit/plugin-rest-endpoint-methods@^5.13.0": + version "5.16.2" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342" + integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw== + dependencies: + "@octokit/types" "^6.39.0" + deprecation "^2.3.1" + +"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": + version "2.1.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" + integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== + dependencies: + "@octokit/types" "^6.0.3" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": + version "5.6.3" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" + integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.1.0" + "@octokit/types" "^6.16.1" + is-plain-object "^5.0.0" + node-fetch "^2.6.7" + universal-user-agent "^6.0.0" + +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0", "@octokit/types@^6.40.0": + version "6.41.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" + integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== + dependencies: + "@octokit/openapi-types" "^12.11.0" + "@sinonjs/commons@^1.7.0": version "1.8.3" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" @@ -2181,6 +2277,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +before-after-hook@^2.2.0: + version "2.2.3" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -2625,6 +2726,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +deprecation@^2.0.0, deprecation@^2.3.1: + version "2.3.1" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -3514,6 +3620,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-port-reachable@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-port-reachable/-/is-port-reachable-4.0.0.tgz#dac044091ef15319c8ab2f34604d8794181f8c2d" @@ -4357,6 +4468,13 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +node-fetch@^2.6.7: + version "2.6.13" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/node-fetch/-/node-fetch-2.6.13.tgz#a20acbbec73c2e09f9007de5cda17104122e0010" + integrity sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA== + dependencies: + whatwg-url "^5.0.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4473,10 +4591,10 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.0: +once@^1.3.0, once@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -5295,6 +5413,11 @@ tr46@^2.1.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + tree-kill@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" @@ -5432,6 +5555,11 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + universalify@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" @@ -5523,6 +5651,11 @@ walker@^1.0.7: dependencies: makeerror "1.0.x" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" @@ -5545,6 +5678,14 @@ whatwg-mimetype@^2.3.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://artylab.expedia.biz/api/npm/public-npm-virtual/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"