diff --git a/.ci/Dockerfile b/.ci/Dockerfile index 1be4afcb39..6e0a0d788d 100644 --- a/.ci/Dockerfile +++ b/.ci/Dockerfile @@ -1,26 +1,15 @@ #syntax=docker/dockerfile:1.2 -FROM node:16 as build -WORKDIR /lambda +FROM node:20 as build +WORKDIR /lambdas RUN apt-get update \ && apt-get install -y zip \ && rm -rf /var/lib/apt/lists/* -FROM build as runner-binaries-syncer -COPY modules/runner-binaries-syncer/lambdas/runner-binaries-syncer /lambda -RUN --mount=type=cache,target=/lambda/node_modules,id=runner-binaries-syncer \ - yarn install && yarn dist - -FROM build as runners -COPY modules/runners/lambdas/runners /lambda -RUN --mount=type=cache,target=/lambda/node_modules,id=runners \ - yarn install && yarn dist - -FROM build as webhook -COPY modules/webhook/lambdas/webhook /lambda -RUN --mount=type=cache,target=/lambda/node_modules,id=webhook \ - yarn install && yarn dist +FROM build as lambdas +COPY lambdas /lambdas +RUN --mount=type=cache,target=/work/node_modules,id=lambdas \ + yarn install --frozen-lockfile && yarn dist && \ + find . -name "*.zip" -exec cp {} . \; FROM scratch as final -COPY --from=runner-binaries-syncer /lambda/runner-binaries-syncer.zip /runner-binaries-syncer.zip -COPY --from=runners /lambda/runners.zip /runners.zip -COPY --from=webhook /lambda/webhook.zip /webhook.zip +COPY --from=lambdas /lambdas/*.zip / diff --git a/.ci/build-yarn.sh b/.ci/build-yarn.sh deleted file mode 100755 index 1283d9ea8b..0000000000 --- a/.ci/build-yarn.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -# Build all the lambda's, output on the default place (inside the lambda module) - -lambdaSrcDirs=("modules/runner-binaries-syncer/lambdas/runner-binaries-syncer" "modules/runners/lambdas/runners" "modules/webhook/lambdas/webhook") -repoRoot=$(dirname $(dirname $(realpath ${BASH_SOURCE[0]}))) - -for lambdaDir in ${lambdaSrcDirs[@]}; do - cd "$repoRoot/${lambdaDir}" - yarn && yarn run dist -done diff --git a/.ci/terraform-init-all.sh b/.ci/terraform-init-all.sh new file mode 100755 index 0000000000..aff4845679 --- /dev/null +++ b/.ci/terraform-init-all.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +# This script will run terraform init in all subdirectories of the examples directory +# required to run tflint via pre-commit + +# only run the script if a uniique pid file exits if not creat it or --force flag is passed +pid="/tmp/philips-labs-terraform-aws-github-runner.pid" +if [ "$1" == "--force" ]; then + rm -f /tmp/philips-labs-terraform-aws-github-runner.pid +fi + +if [ ! -f $pid ]; then + echo $$ > $pid +else + echo "Init all terraform directories will be skipped. To run the script remove the file $pid or run with --force" + exit 0 +fi + +# Change to the examples directory +example_dirs=$(find examples -mindepth 1 -maxdepth 2 -type d | grep -v "templates") +module_dirs=$(find modules -mindepth 1 -maxdepth 2 -type d | grep -v "templates") + +# merge example_dirs and module_dirs in terraform_dirs +terraform_dirs=$(echo $example_dirs $module_dirs "modules/runners/pool" | tr " " "\n" | sort -u | tr "\n" " ") + +for dir in $terraform_dirs; do + # Check if the subdirectory exists in Git + if git rev-parse --is-inside-work-tree &>/dev/null && git ls-files --error-unmatch "$dir" &>/dev/null; then + echo "Running terraform init in ${dir} - supressing output" + pushd "$dir" >/dev/null + terraform init -lockfile=readonly -backend=false &>/dev/null || true + popd >/dev/null + fi +done diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..7fb3b4efc1 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,2 @@ +ARG VARIANT="20-bullseye" +FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT} diff --git a/.devcontainer/bashrc.sh b/.devcontainer/bashrc.sh new file mode 100644 index 0000000000..4caa672b6a --- /dev/null +++ b/.devcontainer/bashrc.sh @@ -0,0 +1,17 @@ +open_workspace() { + local workspace_file=$WORKSPACE/.vscode/gh-runners.code-workspace + + if ! [ -f "$workspace_file" ]; then + echo "🔴 Missing workspace file" + return 1 + fi + + echo "🟡 Opening workspace" + if code "$workspace_file"; then + echo "🟢 Workspace opened" + return 0 + else + echo "🔴 Failed to open workspace" + return 1 + fi +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..b2e87f057c --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,32 @@ +{ + "name": "GitHub Runners AWS", + "build": { "dockerfile": "Dockerfile" }, + "features": { + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/devcontainers/features/terraform:1": {} + }, + + "containerEnv": { + "WORKSPACE": "${containerWorkspaceFolder}" // e.g. /workspaces/my-project + }, + + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "editorconfig.editorconfig", + "esbenp.prettier-vscode", + "firsttris.vscode-jest-runner", + "hashicorp.hcl", + "hashicorp.terraform", + "hashicorp.terraform", + "orta.vscode-jest", + "yzhang.markdown-all-in-one" + ] + } + }, + "postCreateCommand": { + "bash_command": "bash ${containerWorkspaceFolder}/.devcontainer/postCreateScript.sh", + "welcome": "sudo cp -v .devcontainer/welcome.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt || true && sudo cp -v .devcontainer/welcome.txt /workspaces/.codespaces/shared/first-run-notice.txt || true" + } +} diff --git a/.devcontainer/postCreateScript.sh b/.devcontainer/postCreateScript.sh new file mode 100644 index 0000000000..e8ca09e317 --- /dev/null +++ b/.devcontainer/postCreateScript.sh @@ -0,0 +1 @@ +printf "source \$WORKSPACE/.devcontainer/bashrc.sh\n" >> ~/.bashrc diff --git a/.devcontainer/welcome.txt b/.devcontainer/welcome.txt new file mode 100644 index 0000000000..d8b6925fd0 --- /dev/null +++ b/.devcontainer/welcome.txt @@ -0,0 +1,53 @@ +================================================================================ +================================================================================ +=====================================================++++**+++================== +=================================================+++++=********+================ +=============================================+***+=--:-#********+=============== +==========================================+***+=--:::::-+*#*****+=============== +=======================================+*#%*=--:::::::::::-=====+=============== +=====================================+#%%##%*-:::::::::::::::::+================ +===========================++======*#%%#######=-::::::::::::::=+================ +=======================++==---::-+#%%###########+-:::::::::::-+================= +====================+==-::::::-=#%%################+=::::::::+================== +=================++=-:::::::-=#%%%####%%##**########%#*++=-:++================== +===============+=-:::-------*%%%###%%%#=:...:-*############*+=================== +=====. .-====-:--++***+++#%%###%#%%+: .-*###########+==================== +===-. --:-++**+=====+%%%###%%#%*- :*#########*====================== +=== .:==++=========*%%%#####%#%*=. .=#########*======================= +===: :: .==========+%%%%#####%%%%#+=-:::-+#########+======================== +====: :=========#%%%%#####%#**#####*##########+========================== +==== .=========%%%%%####*+=*%##############============================= +====-.... :--------=##%%%%#*==*%##############=::++========================== +========--::---------=-=#%%%#+=#%#############*=-::-*=========================== +======------------=+*=---*#++*%#############+-:::::++=========================== +=====----------=+*+=+---=++*%%%%#########**+-:::::++============================ +===----------+*+=-+*+-=+=*#+=*%%%%%%%#*+==+#=:::-*+============================= +==---------+**+-=**+===**=-=--=+***+======#+-::=+=============================== +==----------+=-=**=:=+*=--++---==========**=:-++================================ +=---------=*=-=**=::::--=*+----=-:::-===**=-=+================================== +=--------=*=-+**+::-=*+=*+-----=. ..=+==+==================================== +=-------==--***+=+**=*+*=------. -+=..===================================== +=------=--=***+**+=-+*+------==. .=+: .===================================== +=--------=*****+---++=-----===== .=: :====================================== +==------=***+=----==-----======- -======================================= +===----=*+=------=-----=========: .======================================== +====--==------------==============--============================================ +======--------================================================================== +================================================================================ +================================================================================ +================================================================================ +================================================================================ +==========================================================================-:-=++ + + +Welcome to the AWS GitHub runners: + +Load the vscode workspace to get started + +Option 1: run `open_workspace` +Option 2: open the workspace file `.vscoe/gh-runners.code-workspace` and load the workspace + +Build the lambda: +- cd lambdas +- yarn instal & yarn run dist + diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d90445f3fe..7d8de4ff6a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,6 +3,10 @@ # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# NPM production dependencies are part of the generated Lambda JavaScript. +# Therefore updates on production are prefixed with fix(component) to trigger releases. +# Development updates are prefixed with chore, and not triggering a release. + version: 2 updates: - package-ecosystem: "github-actions" @@ -13,16 +17,28 @@ updates: interval: "weekly" - package-ecosystem: "npm" - directory: "/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer" - schedule: - interval: "weekly" - - - package-ecosystem: "npm" - directory: "/modules/webhook/lambdas/webhook" - schedule: - interval: "weekly" - - - package-ecosystem: "npm" - directory: "/modules/runners/lambdas/runners" + directory: "/lambdas" schedule: interval: "weekly" + groups: + aws: + patterns: + - "@aws-sdk/*" + octokit: + patterns: + - "@octokit/*" + ignore: + - dependency-name: "aws-sdk*" + update-types: ["version-update:semver-major"] + - dependency-name: "aws-lambda-powertools/*" + update-types: ["version-update:semver-major"] + - dependency-name: "@middy/core" + update-types: ["version-update:semver-major"] + - dependency-name: "@@octokit/*" + update-types: ["version-update:semver-major"] + - dependency-name: "@@octokit/rest" + - dependency-name: "eslint" + update-types: ["version-update:semver-major"] + commit-message: + prefix: "fix(lambda)" + prefix-development: "chore(lambda)" diff --git a/.github/lint/tflint.tfvars b/.github/lint/tflint.tfvars new file mode 100644 index 0000000000..a2b52671e5 --- /dev/null +++ b/.github/lint/tflint.tfvars @@ -0,0 +1,8 @@ +aws_region = "eu-west-1" +github_app = { + id = "0" + key_base64 = "0" + webhook_secret = "0" +} +subnet_ids = [] +vpc_id = null diff --git a/.github/matchers.json b/.github/matchers.json new file mode 100644 index 0000000000..ee4c9a9c1b --- /dev/null +++ b/.github/matchers.json @@ -0,0 +1,18 @@ +{ + "problemMatcher": [ + { + "owner": "tflint-compact", + "pattern": [ + { + "regexp": "^(.+):(\\d+):(\\d+):\\s(Error|Warning|Notice)\\s-\\s(.+)\\s\\((.+)\\)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5, + "code": 6 + } + ] + } + ] +} diff --git a/.github/workflows/auto-approve-dependabot.yml b/.github/workflows/auto-approve-dependabot.yml index e3a07cfe2c..eb72db7cce 100644 --- a/.github/workflows/auto-approve-dependabot.yml +++ b/.github/workflows/auto-approve-dependabot.yml @@ -1,5 +1,4 @@ name: Auto approve dependabot - # Warning: The pull_request_target event is granted a read/write repository # token and can access secrets, even when it is triggered from a fork. Although # the workflow runs in the context of the base of the pull request, you should @@ -8,12 +7,11 @@ name: Auto approve dependabot # the base branch, and to help prevent cache poisoning, you should not save the # cache if there is a possibility that the cache contents were altered. on: pull_request_target - jobs: approve: if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]' runs-on: ubuntu-latest steps: - - uses: hmarr/auto-approve-action@v3.1.0 + - uses: hmarr/auto-approve-action@f0939ea97e9205ef24d872e76833fa908a770363 # ratchet:hmarr/auto-approve-action@v4.0.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/lambda-runner-binaries-syncer.yml b/.github/workflows/lambda-runner-binaries-syncer.yml deleted file mode 100644 index 7691b0a426..0000000000 --- a/.github/workflows/lambda-runner-binaries-syncer.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Lambda Syncer -on: - push: - branches: - - main - pull_request: - paths: - - .github/workflows/lambda-runner-binaries-syncer.yml - - "modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/**" - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - node: [16] - container: - image: node:${{ matrix.node }} - defaults: - run: - working-directory: modules/runner-binaries-syncer/lambdas/runner-binaries-syncer - - steps: - - uses: actions/checkout@v3 - - name: Install dependencies - run: yarn install - - name: Run prettier - run: yarn format-check - - name: Run linter - run: yarn lint - - name: Run tests - run: yarn test - - name: Build distribution - run: yarn build diff --git a/.github/workflows/lambda-runners.yml b/.github/workflows/lambda-runners.yml deleted file mode 100644 index d4ac657c10..0000000000 --- a/.github/workflows/lambda-runners.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Lambda Runners -on: - push: - branches: - - main - pull_request: - paths: - - .github/workflows/lambda-runners.yml - - "modules/runners/lambdas/runners/**" - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - node: [16] - container: - image: node:${{ matrix.node }} - defaults: - run: - working-directory: modules/runners/lambdas/runners - - steps: - - uses: actions/checkout@v3 - - name: Install dependencies - run: yarn install - - name: Run prettier - run: yarn format-check - - name: Run linter - run: yarn lint - - name: Run tests - run: yarn test - - name: Run two tests in isolation - run: | - yarn run test src/scale-runners/scale-up.test.ts -t 'scaleUp with GHES on org level creates a runner with labels in s specific group' --coverage=false - yarn run test src/scale-runners/scale-up.test.ts -t 'scaleUp with public GH on org level creates a runner with labels in s specific group' --coverage=false - - name: Build distribution - run: yarn build diff --git a/.github/workflows/lambda-webhook.yml b/.github/workflows/lambda-webhook.yml deleted file mode 100644 index 2a610da5f0..0000000000 --- a/.github/workflows/lambda-webhook.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Lambda Webhook -on: - push: - branches: - - main - pull_request: - paths: - - .github/workflows/lambda-webhook.yml - - "modules/webhook/lambdas/webhook/**" - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - node: [16] - container: - image: node:${{ matrix.node }} - defaults: - run: - working-directory: modules/webhook/lambdas/webhook - - steps: - - uses: actions/checkout@v3 - - name: Install dependencies - run: yarn install - - name: Run prettier - run: yarn format-check - - name: Run linter - run: yarn lint - - name: Run tests - run: yarn test - - name: Build distribution - run: yarn build diff --git a/.github/workflows/lambda.yml b/.github/workflows/lambda.yml new file mode 100644 index 0000000000..c802c8522b --- /dev/null +++ b/.github/workflows/lambda.yml @@ -0,0 +1,40 @@ +name: Build lambdas +on: + pull_request: + branches: + - main + paths: + - 'lambdas/**' + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node: [20] + container: + image: node:${{ matrix.node }} + defaults: + run: + working-directory: ./lambdas + + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v3.2.0 + - name: Install dependencies + run: yarn install --frozen-lockfile + - name: Run prettier + run: yarn format-check + - name: Run linter + run: yarn lint + - name: Run tests + id: test + run: yarn test + - name: Build distribution + run: yarn build + - name: Upload coverage report + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v31.2 + if: ${{ failure() }} + with: + name: coverage-reports + path: ./**/coverage + retention-days: 5 diff --git a/.github/workflows/packer-build.yml b/.github/workflows/packer-build.yml index ba3a9f5ce6..d3c3be5be0 100644 --- a/.github/workflows/packer-build.yml +++ b/.github/workflows/packer-build.yml @@ -8,31 +8,27 @@ on: - "images/**" - ".github/workflows/packer-build.yml" - "module/runners/templates/**" - env: AWS_REGION: eu-west-1 - + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: verify_packer: name: Verify packer runs-on: ubuntu-latest container: - image: hashicorp/packer:1.7.8 + image: index.docker.io/hashicorp/packer@sha256:297bbbbbbf3ce9e0431ac1e8f02934b20e1197613f877b55dfdb1ebfd94eb748 # ratchet:index.docker.io/hashicorp/packer:1.8.6 strategy: matrix: - image: ["linux-amzn2", "windows-core-2019", "ubuntu-focal"] + image: ["linux-al2023", "windows-core-2019", "windows-core-2022", "ubuntu-focal", "ubuntu-jammy", "ubuntu-jammy-arm64"] defaults: run: working-directory: images/${{ matrix.image }} steps: - name: "Checkout" - uses: actions/checkout@v3 - + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # ratchet:actions/checkout@v4 - name: packer init run: packer init . - - name: check packer formatting run: packer fmt -recursive -check=true . - - name: packer validate - run: packer validate . + run: packer validate -evaluate-datasources . diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 701473e552..4a7856fe5a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,91 +1,49 @@ name: Release build - on: push: branches: - main - v1 + workflow_dispatch: jobs: - prepare: - name: Create dist + release: + name: Release runs-on: ubuntu-latest - container: node:16 - strategy: - matrix: - lambda: ["modules/webhook/lambdas/webhook", "modules/runner-binaries-syncer/lambdas/runner-binaries-syncer", "modules/runners/lambdas/runners"] permissions: - contents: read + contents: write actions: write steps: - - name: Extract lambda name - id: lambda - env: - LAMBDA: ${{ matrix.lambda }} - run: echo "name=${LAMBDA##*/}" >> $GITHUB_OUTPUT - - uses: actions/checkout@v3 - - name: Add zip - run: apt update && apt install zip - - name: Build dist - working-directory: ${{ matrix.lambda }} - run: yarn install && yarn run test && yarn dist - - uses: actions/upload-artifact@v3 + - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - name: ${{ steps.lambda.outputs.name }} - path: ${{ matrix.lambda }}/${{ steps.lambda.outputs.name }}.zip - retention-days: 1 - - release: - name: release - runs-on: ubuntu-latest - needs: - prepare - outputs: - releases_created: ${{ steps.release.outputs.releases_created }} - tag_name: ${{ steps.release.outputs.tag_name }} - steps: + node-version: 20 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # ratchet:actions/checkout@v4 + - name: Build dist + working-directory: lambdas + run: yarn install --frozen-lockfile && yarn run test && yarn dist - name: Get installation token - uses: philips-software/app-token-action@v1.1.2 + uses: philips-software/app-token-action@9f5d57062c9f2beaffafaa9a34f66f824ead63a9 # ratchet:philips-software/app-token-action@v2.0.0 id: token with: app_id: ${{ secrets.FOREST_RELEASER_APP_ID }} app_base64_private_key: ${{ secrets.FOREST_RELEASER_APP_PRIVATE_KEY_BASE64 }} auth_type: installation - - - name: Extract branch name id: branch shell: bash run: echo "name=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT - - name: Release id: release - uses: google-github-actions/release-please-action@5c07f8be172b1f6e90f9c35baf8184461b91b85f # ratchet:google-github-actions/release-please-action@v3 + uses: google-github-actions/release-please-action@e4dc86ba9405554aeba3c6bb2d169500e7d3b4ee # ratchet:google-github-actions/release-please-action@v3 with: default-branch: ${{ steps.branch.outputs.name }} release-type: terraform-module token: ${{ steps.token.outputs.token }} - - assets: - name: upload assets - if: ${{ needs.release.outputs.releases_created }} - needs: release - runs-on: ubuntu-latest - strategy: - matrix: - asset: ["webhook", "runner-binaries-syncer", "runners"] - permissions: - contents: write - actions: read - - steps: - - uses: actions/checkout@v3 - - uses: actions/download-artifact@v3 - with: - name: ${{ matrix.asset }} - - name: Upload Release Asset + if: ${{ steps.release.outputs.releases_created == 'true' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: - gh release upload ${{ needs.release.outputs.tag_name }} ${{ matrix.asset }}.zip + run: | + for f in $(find . -name '*.zip'); do + gh release upload ${{ steps.release.outputs.tag_name }} $f + done diff --git a/.github/workflows/semantic-check.yml b/.github/workflows/semantic-check.yml index f3ae526ef1..a2f4637d6b 100644 --- a/.github/workflows/semantic-check.yml +++ b/.github/workflows/semantic-check.yml @@ -1,24 +1,20 @@ name: "Semantic Check" - on: pull_request_target: types: - opened - edited - synchronize - permissions: contents: read pull-requests: read - jobs: main: name: Semantic Commit Message Check runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - - uses: amannn/action-semantic-pull-request@v5 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # ratchet:actions/checkout@v4 + - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # ratchet:amannn/action-semantic-pull-request@v5 name: Check PR for Semantic Commit Message env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 33e5f536c4..30022522ed 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -3,26 +3,22 @@ on: schedule: - cron: "30 1 * * *" workflow_dispatch: - permissions: issues: write pull-requests: write - jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v6 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # ratchet:actions/stale@v7 with: stale-issue-message: > - This issue has been automatically marked as stale because it has not had - activity in the last 30 days. It will be closed if no further activity occurs. - Thank you for your contributions. + This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs. Thank you for your contributions. + stale-pr-message: > - This pull request has been automatically marked as stale because it has not had - activity in the last 30 days. It will be closed if no further activity occurs. Thank you - for your contributions. - days-before-stale: 30 - days-before-close: 10 + This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed if no further activity occurs. Thank you for your contributions. + + days-before-stale: 90 + days-before-close: 14 close-issue-label: "abandoned" exempt-issue-labels: "stale:exempt" diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index f62c70a25d..b60b31b34a 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -4,8 +4,11 @@ on: branches: - main pull_request: - paths-ignore: - - "modules/*/lambdas/**" + paths: ["**/*.tf", "**/*.hcl", ".github/workflows/terraform.yml"] + +permissions: + contents: read + pull-requests: write env: AWS_REGION: eu-west-1 @@ -14,21 +17,82 @@ jobs: name: Verify module strategy: matrix: - terraform: [1.1.3, "latest"] + terraform: [1.5.6, "latest"] runs-on: ubuntu-latest container: image: hashicorp/terraform:${{ matrix.terraform }} steps: - name: "Checkout" - uses: actions/checkout@v3 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - name: "Fake zip files" # Validate will fail if it cannot find the zip files run: | - touch modules/webhook/lambdas/webhook/webhook.zip - touch modules/runners/lambdas/runners/runners.zip - touch modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/runner-binaries-syncer.zip + touch lambdas/functions/webhook/webhook.zip + touch lambdas/functions/control-plane/runners.zip + touch lambdas/functions/gh-agent-syncer/runner-binaries-syncer.zip + touch lambdas/functions/ami-housekeeper/ami-housekeeper.zip + touch lambdas/functions/termination-watcher/termination-watcher.zip + - name: terraform init + run: terraform init -get -backend=false -input=false + - if: contains(matrix.terraform, '1.5.') + name: check terraform formatting + run: terraform fmt -recursive -check=true -write=false + - if: contains(matrix.terraform, 'latest') # check formatting for the latest release but avoid failing the build + name: check terraform formatting + run: terraform fmt -recursive -check=true -write=false + continue-on-error: true + - name: validate terraform + run: terraform validate + - if: contains(matrix.terraform, '1.5.') + name: Fix for actions/cache on alpine + run: apk add --no-cache tar + continue-on-error: true + - if: contains(matrix.terraform, '1.5.') + uses: actions/cache@ab5e6d0c87105b4c9c2047343972218f562e4319 # v4.0.1 + name: Cache TFLint plugin dir + with: + path: ~/.tflint.d/plugins + key: tflint-${{ hashFiles('.tflint.hcl') }} + - if: contains(matrix.terraform, '1.5.') + name: Setup TFLint + uses: terraform-linters/setup-tflint@19a52fbac37dacb22a09518e4ef6ee234f2d4987 # v4.0.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - if: contains(matrix.terraform, '1.5.') + name: Run TFLint + run: | + tflint --init -c ${GITHUB_WORKSPACE}/.tflint.hcl + tflint -c ${GITHUB_WORKSPACE}/.tflint.hcl --var-file ${GITHUB_WORKSPACE}/.github/lint/tflint.tfvars + + verify_modules: + name: Verify modules + strategy: + fail-fast: false + matrix: + terraform: [1.5.6, "latest"] + module: + [ + "ami-housekeeper", + "download-lambda", + "lambda", + "multi-runner", + "runner-binaries-syncer", + "runners", + "setup-iam-permissions", + "ssm", + "termination-watcher", + "webhook", + ] + defaults: + run: + working-directory: modules/${{ matrix.module }} + runs-on: ubuntu-latest + container: + image: hashicorp/terraform:${{ matrix.terraform }} + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - name: terraform init run: terraform init -get -backend=false -input=false - - if: contains(matrix.terraform, '1.1.') + - if: contains(matrix.terraform, '1.3.') name: check terraform formatting run: terraform fmt -recursive -check=true -write=false - if: contains(matrix.terraform, 'latest') # check formatting for the latest release but avoid failing the build @@ -37,15 +101,45 @@ jobs: continue-on-error: true - name: validate terraform run: terraform validate + - if: contains(matrix.terraform, '1.3.') + name: Fix for actions/cache on alpine + run: apk add --no-cache tar + continue-on-error: true + - if: contains(matrix.terraform, '1.3.') + uses: actions/cache@v4 + name: Cache TFLint plugin dir + with: + path: ~/.tflint.d/plugins + key: tflint-${{ hashFiles('.tflint.hcl') }} + - if: contains(matrix.terraform, '1.3.') + name: Setup TFLint + uses: terraform-linters/setup-tflint@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - if: contains(matrix.terraform, '1.3.') + name: Run TFLint + working-directory: ${{ github.workspace }} + run: | + tflint --init -c ${GITHUB_WORKSPACE}/.tflint.hcl --chdir modules/${{ matrix.module }} + tflint -f compact -c ${GITHUB_WORKSPACE}/.tflint.hcl --var-file ${GITHUB_WORKSPACE}/.github/lint/tflint.tfvars --chdir modules/${{ matrix.module }} verify_examples: name: Verify examples strategy: fail-fast: false matrix: - terraform: [1.0.11, 1.1.3, "latest"] + terraform: [1.5.6, "latest"] example: - ["default", "ubuntu", "prebuilt", "arm64", "ephemeral", "windows"] + [ + "default", + "ubuntu", + "prebuilt", + "arm64", + "ephemeral", + "termination-watcher", + "windows", + "multi-runner", + ] defaults: run: working-directory: examples/${{ matrix.example }} @@ -53,15 +147,36 @@ jobs: container: image: hashicorp/terraform:${{ matrix.terraform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - name: terraform init run: terraform init -get -backend=false -input=false - - if: contains(matrix.terraform, '1.1.') + - if: contains(matrix.terraform, '1.5.') name: check terraform formatting run: terraform fmt -recursive -check=true -write=false - if: contains(matrix.terraform, 'latest') # check formatting for the latest release but avoid failing the build name: check terraform formatting run: terraform fmt -recursive -check=true -write=false continue-on-error: true - - name: validate terraform011 + - name: validate terraform run: terraform validate + - if: contains(matrix.terraform, '1.5.') + name: Fix for actions/cache on alpine + run: apk add --no-cache tar + continue-on-error: true + - if: contains(matrix.terraform, '1.5.') + uses: actions/cache@v4 + name: Cache TFLint plugin dir + with: + path: ~/.tflint.d/plugins + key: tflint-${{ hashFiles('.tflint.hcl') }} + - if: contains(matrix.terraform, '1.5.') + name: Setup TFLint + uses: terraform-linters/setup-tflint@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + - if: contains(matrix.terraform, '1.5.') + name: Run TFLint + working-directory: ${{ github.workspace }} + run: | + tflint --init -c ${GITHUB_WORKSPACE}/.tflint.hcl --chdir modules/${{ matrix.module }} + tflint -f compact -c ${GITHUB_WORKSPACE}/.tflint.hcl --var-file ${GITHUB_WORKSPACE}/.github/lint/tflint.tfvars --chdir examples/${{ matrix.example }} diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml new file mode 100644 index 0000000000..debc7215c7 --- /dev/null +++ b/.github/workflows/update-docs.yml @@ -0,0 +1,85 @@ +name: Update docs +on: + push: + paths: + - "**/*.tf" + - "**/*.md" + - ".github/workflows/update-docs.yml" + +permissions: + contents: write + pull-requests: write + +jobs: + docs: + # update docs after merge back to develop + name: Auto update terraform docs + runs-on: ubuntu-latest + steps: + - uses: philips-software/app-token-action@9f5d57062c9f2beaffafaa9a34f66f824ead63a9 # v2.0.0 + id: app + with: + app_id: ${{ vars.FOREST_PR_BOT_APP_ID }} + app_base64_private_key: ${{ secrets.FOREST_PR_BOT_APP_KEY_BASE64 }} + auth_type: installation + org: philips-labs + + - name: Checkout with GITHUB Action token + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # ratchet:actions/checkout@v4 + with: + token: ${{ steps.app.outputs.token }} + + # use an app to ensure CI is triggered + - name: Generate TF docs + if: github.repository_owner == 'philips-labs' + uses: terraform-docs/gh-actions@e47bfa196e79fa50987ef391be236d9d97b0c786 # ratchet:terraform-docs/gh-actions@v1.2.0 + with: + find-dir: . + git-commit-message: "docs: auto update terraform docs" + git-push: ${{ github.ref != 'refs/heads/main' || github.repository_owner != 'philips-labs' }} + git-push-user-name: forest-pr|bot + git-push-user-email: "forest-pr[bot]@users.noreply.github.com" + + - name: Generate TF docs (forks) + if: github.repository_owner != 'philips-labs' + uses: terraform-docs/gh-actions@e47bfa196e79fa50987ef391be236d9d97b0c786 # ratchet:terraform-docs/gh-actions@v1.2.0 + with: + find-dir: . + git-commit-message: "docs: auto update terraform docs" + git-push: ${{ github.ref != 'refs/heads/main' || github.repository_owner != 'philips-labs' }} + + # change docs via PR in case of locked main branch + - name: Create Pull Request (main branch only) + if: github.ref == 'refs/heads/main' && github.repository_owner == 'philips-labs' + uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # ratchet:peter-evans/create-pull-request@v6.1.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "docs: auto update terraform docs" + title: "docs: Update Terraform docs" + branch: update-docs + branch-suffix: random + base: ${{ github.event.pull_request.base.ref }} + delete-branch: true + + deploy-pages: + needs: [docs] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # ratchet:actions/checkout@v4 + - name: Configure Git Credentials + run: | + git config user.name github-actions[bot] + git config --global user.email "github-actions[bot]@users.noreply.github.com" + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v4 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: pip install mkdocs-material + - run: pip install mkdocs-material-extensions + - run: mkdocs gh-deploy --force -c -b gh-pages diff --git a/.gitignore b/.gitignore index 9de7a7047d..bd9e5760f1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,8 +18,8 @@ secrets.auto.tfvars *.gz *.tgz *.env* -.vscode **/coverage/* -node_modules/ \ No newline at end of file +node_modules/ +site/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cfabefad46..bb5b39b5a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,12 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.52.0 + rev: v1.83.5 hooks: - id: terraform_fmt - id: terraform_tflint - - id: terraform_docs + args: + - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl --var-file __GIT_WORKING_DIR__/.github/lint/tflint.tfvars - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.5.0 hooks: - id: check-merge-conflict diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000000..b4043fb5eb --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,45 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.31.0" + constraints = "~> 5.27" + hashes = [ + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.0" + constraints = "~> 3.0" + hashes = [ + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + ] +} diff --git a/.tflint.hcl b/.tflint.hcl new file mode 100644 index 0000000000..bcebefe93e --- /dev/null +++ b/.tflint.hcl @@ -0,0 +1,22 @@ +config { + format = "compact" + module = true +} + +plugin "aws" { + enabled = true + version = "0.30.0" + source = "github.com/terraform-linters/tflint-ruleset-aws" +} + +rule "terraform_comment_syntax" { + enabled = true +} + +rule "terraform_naming_convention" { + enabled = true +} + +rule "terraform_documented_variables" { + enabled = true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 68a2778682..1a8f1b1053 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,6 +5,7 @@ // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp "editorconfig.editorconfig", "yzhang.markdown-all-in-one", - "hashicorp.terraform" + "hashicorp.terraform", + "firsttris.vscode-jest-runner" ] -} \ No newline at end of file +} diff --git a/.vscode/gh-runners.code-workspace b/.vscode/gh-runners.code-workspace new file mode 100644 index 0000000000..dd9183b23c --- /dev/null +++ b/.vscode/gh-runners.code-workspace @@ -0,0 +1,18 @@ +{ + "folders": [ + { + "name": "✨ root", + "path": ".." + }, + { + "name": "🚀 lambdas", + "path": "../lambdas" + } + ], + "settings": { + "jest.autoRun": "on", + "jest.disabledWorkspaceFolders": [ + "✨ root" + ] + } +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 1635e284bb..9e26dfeeb6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1 @@ -{ - "sonarlint.rules": { - "javascript:S4123": { - "level": "off" - } - } -} \ No newline at end of file +{} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c34968b13..20067a82ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,1003 @@ # Changelog -## [1.13.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.12.0...v1.13.0) (2022-10-14) +## [5.12.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.12.1...v5.12.2) (2024-07-12) + + +### Bug Fixes + +* remove job start hook with senstive information ([#3986](https://github.com/philips-labs/terraform-aws-github-runner/issues/3986)) ([bbcb470](https://github.com/philips-labs/terraform-aws-github-runner/commit/bbcb4707f698b29c470c0aadf81c9ac2c37781f8)), closes [#3980](https://github.com/philips-labs/terraform-aws-github-runner/issues/3980) + +## [5.12.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.12.0...v5.12.1) (2024-07-05) + + +### Bug Fixes + +* dependency updates lambda ([#3965](https://github.com/philips-labs/terraform-aws-github-runner/issues/3965)) ([a6df2b6](https://github.com/philips-labs/terraform-aws-github-runner/commit/a6df2b65dd74a911e9403f7ae7a03230d5003e8e)) +* improve logging when there is an error retrieving ssm parameters ([#3962](https://github.com/philips-labs/terraform-aws-github-runner/issues/3962)) ([1498c8c](https://github.com/philips-labs/terraform-aws-github-runner/commit/1498c8c2bdc4e1df8fd3671f2cc2c59d86c3eb92)) + +## [5.12.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.11.0...v5.12.0) (2024-06-28) + + +### Features + +* add support for matcher config tiering options ([#3953](https://github.com/philips-labs/terraform-aws-github-runner/issues/3953)) ([5f9d9eb](https://github.com/philips-labs/terraform-aws-github-runner/commit/5f9d9eb3f9fbda10495b9a2194dc91867942276e)) +* **lambda:** add option to define explicit lambda tags ([#3934](https://github.com/philips-labs/terraform-aws-github-runner/issues/3934)) ([7e98943](https://github.com/philips-labs/terraform-aws-github-runner/commit/7e98943c0b8962ebd0a231da233b431ba692c321)) + + +### Bug Fixes + +* **lambda:** bump braces from 3.0.2 to 3.0.3 in /lambdas ([#3944](https://github.com/philips-labs/terraform-aws-github-runner/issues/3944)) ([1aef82b](https://github.com/philips-labs/terraform-aws-github-runner/commit/1aef82b19fd1b53194b07ba650649f6d314e597c)) +* **lambda:** bump the aws group across 1 directory with 2 updates ([#3955](https://github.com/philips-labs/terraform-aws-github-runner/issues/3955)) ([2e094cf](https://github.com/philips-labs/terraform-aws-github-runner/commit/2e094cf242fd910d2e2451ece3946f7232f048b7)) +* **lambda:** bump the aws group across 1 directory with 6 updates ([#3949](https://github.com/philips-labs/terraform-aws-github-runner/issues/3949)) ([76fe9af](https://github.com/philips-labs/terraform-aws-github-runner/commit/76fe9af0ad25f2d7647c1c838c6a144b55a1105d)) +* **webhook:** Don't log warning when secondary job queue is empty ([#3942](https://github.com/philips-labs/terraform-aws-github-runner/issues/3942)) ([ef25bd4](https://github.com/philips-labs/terraform-aws-github-runner/commit/ef25bd44717d282cc123ada570b0b03cf76b4d7f)) +* **webhook:** Don't set `${SQS_WORKFLOW_JOB_QUEUE}` to empty string ([#3943](https://github.com/philips-labs/terraform-aws-github-runner/issues/3943)) ([6c48dff](https://github.com/philips-labs/terraform-aws-github-runner/commit/6c48dffff558dba78d013f10764fb65329b6523e)) + +## [5.11.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.10.4...v5.11.0) (2024-05-22) + + +### Features + +* add variable to configure ebs optimization for runner instances ([479b779](https://github.com/philips-labs/terraform-aws-github-runner/commit/479b779a71c77a62dd28d247f8a74cb75ce083f0)) +* add variable to configure ebs optimization for runner instances ([#3901](https://github.com/philips-labs/terraform-aws-github-runner/issues/3901)) ([479b779](https://github.com/philips-labs/terraform-aws-github-runner/commit/479b779a71c77a62dd28d247f8a74cb75ce083f0)) +* Restrict instance SSM permissions ([#3918](https://github.com/philips-labs/terraform-aws-github-runner/issues/3918)) ([9399cf2](https://github.com/philips-labs/terraform-aws-github-runner/commit/9399cf29bec963dfa305f367f37c098a76130371)) + + +### Bug Fixes + +* adding missing permissions to boundaries ([#3873](https://github.com/philips-labs/terraform-aws-github-runner/issues/3873)) ([93e8d27](https://github.com/philips-labs/terraform-aws-github-runner/commit/93e8d2746b647539212dbc65887ec748a1d734b7)) +* **lambda:** bump the aws group across 1 directory with 6 updates ([#3907](https://github.com/philips-labs/terraform-aws-github-runner/issues/3907)) ([50dda9a](https://github.com/philips-labs/terraform-aws-github-runner/commit/50dda9a465229bdb8d106e7ebc5d5b1de115a286)) + +## [5.10.4](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.10.3...v5.10.4) (2024-05-06) + + +### Bug Fixes + +* **lambda:** bump ejs from 3.1.9 to 3.1.10 in /lambdas ([#3887](https://github.com/philips-labs/terraform-aws-github-runner/issues/3887)) ([4cca21f](https://github.com/philips-labs/terraform-aws-github-runner/commit/4cca21fa5c44316e2ef2574563b24218f8ae090d)) +* **lambda:** bump the aws group across 1 directory with 6 updates ([#3890](https://github.com/philips-labs/terraform-aws-github-runner/issues/3890)) ([d1cd712](https://github.com/philips-labs/terraform-aws-github-runner/commit/d1cd712204b678a878f22eea75e540cb28d6a3ad)) +* Typo in env vars for scale-up lambda ([#3891](https://github.com/philips-labs/terraform-aws-github-runner/issues/3891)) ([f4ecf46](https://github.com/philips-labs/terraform-aws-github-runner/commit/f4ecf466014d7d51aed238aa851290908d3c7972)) + +## [5.10.3](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.10.2...v5.10.3) (2024-05-03) + + +### Bug Fixes + +* revert depedency update / broken release 5.10.2 ([#3885](https://github.com/philips-labs/terraform-aws-github-runner/issues/3885)) ([7464f2b](https://github.com/philips-labs/terraform-aws-github-runner/commit/7464f2bbb401c9c1b07d252c2572a4a970468e95)) + +## [5.10.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.10.1...v5.10.2) (2024-04-25) + + +### Bug Fixes + +* change log level for termination watcher if no match ([#3866](https://github.com/philips-labs/terraform-aws-github-runner/issues/3866)) ([649ad35](https://github.com/philips-labs/terraform-aws-github-runner/commit/649ad35b63f519739354b8bc801dff6c70d66f46)) +* update dependencies ([#3867](https://github.com/philips-labs/terraform-aws-github-runner/issues/3867)) ([85b5aac](https://github.com/philips-labs/terraform-aws-github-runner/commit/85b5aac73931cebdeb779a86118d7b5043286493)) + +## [5.10.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.10.0...v5.10.1) (2024-04-24) + + +### Bug Fixes + +* Add missing webhook_events_workflow_job_queue_policy to multi-runner queue ([#3848](https://github.com/philips-labs/terraform-aws-github-runner/issues/3848)) ([a8cba4e](https://github.com/philips-labs/terraform-aws-github-runner/commit/a8cba4e3795c6105636530ede9360e3123c92c3a)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3861](https://github.com/philips-labs/terraform-aws-github-runner/issues/3861)) ([6119354](https://github.com/philips-labs/terraform-aws-github-runner/commit/611935472f8551c103544bc074c7ae419b455528)) +* **lambda:** bump typescript from 5.3.3 to 5.4.5 in /lambdas ([#3863](https://github.com/philips-labs/terraform-aws-github-runner/issues/3863)) ([e3f3d77](https://github.com/philips-labs/terraform-aws-github-runner/commit/e3f3d779a8f66f2933da0600c6ef3de252fb440d)) +* webhook expects REPOSITORY_ALLOW_LIST env var ([#3856](https://github.com/philips-labs/terraform-aws-github-runner/issues/3856)) ([0006ab9](https://github.com/philips-labs/terraform-aws-github-runner/commit/0006ab9fb5880fb1daf31b3e1b8d218e7b86105b)) + +## [5.10.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.9.0...v5.10.0) (2024-04-17) + + +### Features + +* add spot termination watcher (beta) ([#3789](https://github.com/philips-labs/terraform-aws-github-runner/issues/3789)) ([b2dc794](https://github.com/philips-labs/terraform-aws-github-runner/commit/b2dc794f08c932470dae846dad0e0a5f33a68cc4)) +* allow caller to provide custom userdata ([#3798](https://github.com/philips-labs/terraform-aws-github-runner/issues/3798)) ([ac49daf](https://github.com/philips-labs/terraform-aws-github-runner/commit/ac49daf4afb14b6710d2d652bc2c0f51fc2af98f)) +* Allow to disable runner max scaling check ([#3849](https://github.com/philips-labs/terraform-aws-github-runner/issues/3849)) ([e05a043](https://github.com/philips-labs/terraform-aws-github-runner/commit/e05a043b7354f42f391a1b5319bc850d4e8b2c02)) + + +### Bug Fixes + +* **lambda:** bump axios from 1.6.7 to 1.6.8 in /lambdas ([#3814](https://github.com/philips-labs/terraform-aws-github-runner/issues/3814)) ([513b22f](https://github.com/philips-labs/terraform-aws-github-runner/commit/513b22f6291d9437aae41367098096ca6377547b)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3834](https://github.com/philips-labs/terraform-aws-github-runner/issues/3834)) ([e7e56ea](https://github.com/philips-labs/terraform-aws-github-runner/commit/e7e56ea9466feedec46c41f0834ebfd05e6f512f)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3846](https://github.com/philips-labs/terraform-aws-github-runner/issues/3846)) ([9303a10](https://github.com/philips-labs/terraform-aws-github-runner/commit/9303a108dfd12ff0c63e7aeb55aa814c7f14619c)) +* **lambda:** bump the aws group in /lambdas with 6 updates ([#3818](https://github.com/philips-labs/terraform-aws-github-runner/issues/3818)) ([9a9031e](https://github.com/philips-labs/terraform-aws-github-runner/commit/9a9031ead20546f6a3b939435a801e5aeb8264b8)) + +## [5.9.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.8.0...v5.9.0) (2024-03-14) + + +### Features + +* **runners:** add retry logic to default install and start script for dnf operations ([#3787](https://github.com/philips-labs/terraform-aws-github-runner/issues/3787)) ([6a8e1f0](https://github.com/philips-labs/terraform-aws-github-runner/commit/6a8e1f03e122f99006c488e544c6cf3b672fa304)) +* Update default runtime from nodejs18.x to nodejs20.x ([#3791](https://github.com/philips-labs/terraform-aws-github-runner/issues/3791)) ([11ace32](https://github.com/philips-labs/terraform-aws-github-runner/commit/11ace32b0a1283c65a19fe7035c0a9835f6cdeab)) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 6 updates ([#3803](https://github.com/philips-labs/terraform-aws-github-runner/issues/3803)) ([eedbf52](https://github.com/philips-labs/terraform-aws-github-runner/commit/eedbf525a9f1d377d8a1f9fb50d1842eb8947afe)) + +## [5.8.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.7.1...v5.8.0) (2024-02-27) + + +### Features + +* Add option to set lambda memory increase webhook memory ([#3778](https://github.com/philips-labs/terraform-aws-github-runner/issues/3778)) ([40bceb6](https://github.com/philips-labs/terraform-aws-github-runner/commit/40bceb6db1d4bed7959b35a7b23f2b2d21ddc447)) +* migrate webhook runner configuration to SSM ([#3728](https://github.com/philips-labs/terraform-aws-github-runner/issues/3728)) ([32492e3](https://github.com/philips-labs/terraform-aws-github-runner/commit/32492e3780509d4ff67d0ed3ad55f3506174974c)) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 6 updates ([#3772](https://github.com/philips-labs/terraform-aws-github-runner/issues/3772)) ([3549bc1](https://github.com/philips-labs/terraform-aws-github-runner/commit/3549bc1824fcf15b7b008eb6ea455a89ae3278df)) +* **lambda:** bump the aws group in /lambdas with 6 updates ([#3783](https://github.com/philips-labs/terraform-aws-github-runner/issues/3783)) ([b850e85](https://github.com/philips-labs/terraform-aws-github-runner/commit/b850e853e221e4f1026f31e1bfc8d4c73d08c212)) +* **lambda:** bump the octokit group in /lambdas with 2 updates ([#3773](https://github.com/philips-labs/terraform-aws-github-runner/issues/3773)) ([de9985a](https://github.com/philips-labs/terraform-aws-github-runner/commit/de9985a9f6babf83b3c2149247db7ecee602a500)) + +## [5.7.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.7.0...v5.7.1) (2024-02-13) + + +### Bug Fixes + +* add retry logic to runner start script for libicu download ([#3748](https://github.com/philips-labs/terraform-aws-github-runner/issues/3748)) ([1b4597b](https://github.com/philips-labs/terraform-aws-github-runner/commit/1b4597b613dc46dcc63cacb546ff4ce489cd731f)) +* **lambda:** bump the aws group in /lambdas with 6 updates ([#3762](https://github.com/philips-labs/terraform-aws-github-runner/issues/3762)) ([e43fd80](https://github.com/philips-labs/terraform-aws-github-runner/commit/e43fd80324dd1e553dc81720b39893f1c6dd97d4)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3763](https://github.com/philips-labs/terraform-aws-github-runner/issues/3763)) ([77586c5](https://github.com/philips-labs/terraform-aws-github-runner/commit/77586c5efb6a4e33bb2c056867738c13559292b9)) + +## [5.7.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.6.3...v5.7.0) (2024-02-12) + + +### Features + +* allow setting VPC and subnets per runner ([#3467](https://github.com/philips-labs/terraform-aws-github-runner/issues/3467)) ([1288c81](https://github.com/philips-labs/terraform-aws-github-runner/commit/1288c81de1b9905a71b8f44c03efaf526384b0f2)) + + +### Bug Fixes + +* Correct typo in README.md ([#3758](https://github.com/philips-labs/terraform-aws-github-runner/issues/3758)) ([7186c1c](https://github.com/philips-labs/terraform-aws-github-runner/commit/7186c1ce48cdeb4ec017d3303f8b7f69d609891a)) +* **images:** avoid wrong AMI selected for ubuntu jammy ([#3747](https://github.com/philips-labs/terraform-aws-github-runner/issues/3747)) ([595aec9](https://github.com/philips-labs/terraform-aws-github-runner/commit/595aec9833dd1d1b1383449c0a8ea2284ed98406)) +* **lambda:** bump @aws-lambda-powertools/logger from 1.17.0 to 1.18.0 in /lambdas ([#3754](https://github.com/philips-labs/terraform-aws-github-runner/issues/3754)) ([98131ff](https://github.com/philips-labs/terraform-aws-github-runner/commit/98131ffd44b735e120d64e9a77020dc5733021d0)) +* **lambda:** bump axios from 1.6.2 to 1.6.7 in /lambdas ([#3755](https://github.com/philips-labs/terraform-aws-github-runner/issues/3755)) ([80a34bd](https://github.com/philips-labs/terraform-aws-github-runner/commit/80a34bd7eaafa49c774263ae5406bdc74255d250)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3730](https://github.com/philips-labs/terraform-aws-github-runner/issues/3730)) ([7854a5f](https://github.com/philips-labs/terraform-aws-github-runner/commit/7854a5f7ed0cdbcbedd746f34074637898d5125d)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3743](https://github.com/philips-labs/terraform-aws-github-runner/issues/3743)) ([7ca40ef](https://github.com/philips-labs/terraform-aws-github-runner/commit/7ca40ef1f952403e53e78193eceaea1b1bb67ff6)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3753](https://github.com/philips-labs/terraform-aws-github-runner/issues/3753)) ([9f3aa68](https://github.com/philips-labs/terraform-aws-github-runner/commit/9f3aa689f1fdd574dc2980fb3d3f6166bd99238b)) +* windows userdata does not support gzip ([#3759](https://github.com/philips-labs/terraform-aws-github-runner/issues/3759)) ([b74df54](https://github.com/philips-labs/terraform-aws-github-runner/commit/b74df549521f7d8d54eb0e1e436803934cabac3f)) + +## [5.6.3](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.6.2...v5.6.3) (2024-01-16) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3720](https://github.com/philips-labs/terraform-aws-github-runner/issues/3720)) ([9a17b13](https://github.com/philips-labs/terraform-aws-github-runner/commit/9a17b132c999b392e19af690362340508debe1f7)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3721](https://github.com/philips-labs/terraform-aws-github-runner/issues/3721)) ([9b13c09](https://github.com/philips-labs/terraform-aws-github-runner/commit/9b13c099598728d91f58a79b46d460fad12c94a1)) +* **runners:** zip base64 encoded user data to avoid size limits ([#3717](https://github.com/philips-labs/terraform-aws-github-runner/issues/3717)) ([f2bbcb1](https://github.com/philips-labs/terraform-aws-github-runner/commit/f2bbcb16e2c99dbf58057680564f517e74599d73)), closes [#3700](https://github.com/philips-labs/terraform-aws-github-runner/issues/3700) + +## [5.6.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.6.1...v5.6.2) (2024-01-12) + + +### Bug Fixes + +* **multi-runner:** remove renundant default labels ([#3715](https://github.com/philips-labs/terraform-aws-github-runner/issues/3715)) ([9353734](https://github.com/philips-labs/terraform-aws-github-runner/commit/93537347538a8a57516ae1737b96d4c37319af32)) +* **webhook-github-app:** Allow new lines in base64 key for module webhook-github-app ([#3714](https://github.com/philips-labs/terraform-aws-github-runner/issues/3714)) ([57f056d](https://github.com/philips-labs/terraform-aws-github-runner/commit/57f056dc4a57896d702c8bf056fceb8b3c6e77f8)) + +## [5.6.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.6.0...v5.6.1) (2024-01-10) + + +### Bug Fixes + +* **lambda:** bump follow-redirects from 1.15.2 to 1.15.4 in /lambdas ([#3712](https://github.com/philips-labs/terraform-aws-github-runner/issues/3712)) ([97c5fcf](https://github.com/philips-labs/terraform-aws-github-runner/commit/97c5fcf6fe3b94b2af1646e8c18e00b69e608a04)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3699](https://github.com/philips-labs/terraform-aws-github-runner/issues/3699)) ([6fa667f](https://github.com/philips-labs/terraform-aws-github-runner/commit/6fa667fae7e4302cf643bcdb4ff3c91b1e4ed8d1)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3705](https://github.com/philips-labs/terraform-aws-github-runner/issues/3705)) ([477c59b](https://github.com/philips-labs/terraform-aws-github-runner/commit/477c59b3516558b02c98d56db652e634015a953c)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3706](https://github.com/philips-labs/terraform-aws-github-runner/issues/3706)) ([af40f28](https://github.com/philips-labs/terraform-aws-github-runner/commit/af40f28c42d9be68d5bd945624ce390e87f87374)) +* Loosen the AWS Terraform provider constraint ([#3708](https://github.com/philips-labs/terraform-aws-github-runner/issues/3708)) ([649da42](https://github.com/philips-labs/terraform-aws-github-runner/commit/649da42de76a8b3ed895f0f0e6b08d4719198592)) +* workflow job event queue misconfiguration. ([#3710](https://github.com/philips-labs/terraform-aws-github-runner/issues/3710)) ([0a2577e](https://github.com/philips-labs/terraform-aws-github-runner/commit/0a2577ed250c73ac8272132f7b39874b9957fdbd)) + +## [5.6.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.5.2...v5.6.0) (2023-12-20) + + +### Features + +* upgrade lambda runtime from 18x to 20x ([#3682](https://github.com/philips-labs/terraform-aws-github-runner/issues/3682)) ([02dd3e6](https://github.com/philips-labs/terraform-aws-github-runner/commit/02dd3e64db3a8a026613f010f6654970c8daf6c2)) + + +### Bug Fixes + +* **lambda:** bump @aws-lambda-powertools/tracer from 1.16.0 to 1.17.0 in /lambdas ([#3675](https://github.com/philips-labs/terraform-aws-github-runner/issues/3675)) ([b3536f7](https://github.com/philips-labs/terraform-aws-github-runner/commit/b3536f7cb37a36643cf7beffd1629440bda221ca)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3671](https://github.com/philips-labs/terraform-aws-github-runner/issues/3671)) ([677965d](https://github.com/philips-labs/terraform-aws-github-runner/commit/677965df7d392be7a5176837f74b6698b70a4947)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3672](https://github.com/philips-labs/terraform-aws-github-runner/issues/3672)) ([67facac](https://github.com/philips-labs/terraform-aws-github-runner/commit/67facac961890186eed199ffa685211fbc933adb)) +* Replace deprecate aws_cloudwatch_event_rule.is_enabled, requires provide upgrade ([#3655](https://github.com/philips-labs/terraform-aws-github-runner/issues/3655)) ([3c78f65](https://github.com/philips-labs/terraform-aws-github-runner/commit/3c78f652a4b2569e1e93ce739e8a9cda62c2128e)) + +## [5.5.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.5.1...v5.5.2) (2023-12-16) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3661](https://github.com/philips-labs/terraform-aws-github-runner/issues/3661)) ([81da0be](https://github.com/philips-labs/terraform-aws-github-runner/commit/81da0becd678079e23d0e67a66b8a85a93d09101)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3662](https://github.com/philips-labs/terraform-aws-github-runner/issues/3662)) ([76697e6](https://github.com/philips-labs/terraform-aws-github-runner/commit/76697e69c41dd3524496977869c0b6aaa6a07d36)) + +## [5.5.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.5.0...v5.5.1) (2023-12-07) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3647](https://github.com/philips-labs/terraform-aws-github-runner/issues/3647)) ([aa0de8d](https://github.com/philips-labs/terraform-aws-github-runner/commit/aa0de8d4f742cf0cc61e87010d70d8aca056f687)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3648](https://github.com/philips-labs/terraform-aws-github-runner/issues/3648)) ([e5dc96b](https://github.com/philips-labs/terraform-aws-github-runner/commit/e5dc96b49af98da1630aa96bbde0f2589b145941)) + +## [5.5.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.4.2...v5.5.0) (2023-11-30) + + +### Features + +* add failover to on-demand in case request is failing ([#3409](https://github.com/philips-labs/terraform-aws-github-runner/issues/3409)) ([d71e631](https://github.com/philips-labs/terraform-aws-github-runner/commit/d71e631f3befe7aa15a56c52ba8ead2be71be460)) + + +### Bug Fixes + +* add runner name prefix to context of scale-up lambda ([#3644](https://github.com/philips-labs/terraform-aws-github-runner/issues/3644)) ([2936edd](https://github.com/philips-labs/terraform-aws-github-runner/commit/2936edde98bbd19349396ec575d810caa4f75efb)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3635](https://github.com/philips-labs/terraform-aws-github-runner/issues/3635)) ([9615e53](https://github.com/philips-labs/terraform-aws-github-runner/commit/9615e53af45ae80884ea02570603dd9e614140d4)) +* **lambda:** bump the octokit group in /lambdas with 1 update ([#3636](https://github.com/philips-labs/terraform-aws-github-runner/issues/3636)) ([876db0c](https://github.com/philips-labs/terraform-aws-github-runner/commit/876db0ce2bf6f39ab3eb4264512086aafbeb65f1)) + +## [5.4.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.4.1...v5.4.2) (2023-11-26) + + +### Bug Fixes + +* **examples:** webhook-github-app multiple character args ([#3625](https://github.com/philips-labs/terraform-aws-github-runner/issues/3625)) ([941682e](https://github.com/philips-labs/terraform-aws-github-runner/commit/941682e8ffa04df6976f8f2f9e91ffe3aa4f6b66)) +* **lambda:** bump @aws-lambda-powertools/tracer from 1.14.2 to 1.16.0 in /lambdas ([#3622](https://github.com/philips-labs/terraform-aws-github-runner/issues/3622)) ([ba73565](https://github.com/philips-labs/terraform-aws-github-runner/commit/ba73565220179dd685c19d5c0cb57634f9d24fa8)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3620](https://github.com/philips-labs/terraform-aws-github-runner/issues/3620)) ([1b944d5](https://github.com/philips-labs/terraform-aws-github-runner/commit/1b944d59bbbed7a6b60ba4d205440ff730208230)) +* **lambda:** bump the octokit group in /lambdas with 2 updates ([#3621](https://github.com/philips-labs/terraform-aws-github-runner/issues/3621)) ([c54e8c8](https://github.com/philips-labs/terraform-aws-github-runner/commit/c54e8c896b4f6a19dcc15172671fdf31de6e371d)) + +## [5.4.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.4.0...v5.4.1) (2023-11-17) + + +### Bug Fixes + +* **lambda:** bump @aws-lambda-powertools/logger from 1.14.0 to 1.14.2 in /lambdas ([#3611](https://github.com/philips-labs/terraform-aws-github-runner/issues/3611)) ([1292c6b](https://github.com/philips-labs/terraform-aws-github-runner/commit/1292c6bf262c088be70119857327f332ddfea4ec)) +* **lambda:** bump @middy/core from 3.6.2 to 4.7.0 in /lambdas ([#3609](https://github.com/philips-labs/terraform-aws-github-runner/issues/3609)) ([2d0f039](https://github.com/philips-labs/terraform-aws-github-runner/commit/2d0f039f6b2e0b0bec4cb501e4797820c26531e8)) +* **lambda:** bump axios from 1.5.1 to 1.6.0 in /lambdas ([#3604](https://github.com/philips-labs/terraform-aws-github-runner/issues/3604)) ([a316b82](https://github.com/philips-labs/terraform-aws-github-runner/commit/a316b8226cb05f5ed9b586549892fa0ab4cb52b8)) +* **lambda:** bump axios from 1.6.0 to 1.6.1 in /lambdas ([#3612](https://github.com/philips-labs/terraform-aws-github-runner/issues/3612)) ([ab3627f](https://github.com/philips-labs/terraform-aws-github-runner/commit/ab3627f989564aa65efaa6b33c666870a9710aa8)) +* remove unused environment variable ([#3616](https://github.com/philips-labs/terraform-aws-github-runner/issues/3616)) ([bb68562](https://github.com/philips-labs/terraform-aws-github-runner/commit/bb68562953304dc1f6a6d6d5d2309db5e1e823c0)) + +## [5.4.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.3.0...v5.4.0) (2023-11-08) + + +### Features + +* added changes to enable tracing in lambdas. ([#3554](https://github.com/philips-labs/terraform-aws-github-runner/issues/3554)) ([970e8a6](https://github.com/philips-labs/terraform-aws-github-runner/commit/970e8a657a9a3d62966c75c6738eba7292c77aa8)) + + +### Bug Fixes + +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3595](https://github.com/philips-labs/terraform-aws-github-runner/issues/3595)) ([581a4bf](https://github.com/philips-labs/terraform-aws-github-runner/commit/581a4bff74a22c6d9577c35c6bb683d26cfd5cff)) + +## [5.3.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.2.1...v5.3.0) (2023-11-03) + + +### Features + +* order label matchers for multi-runners ([#3591](https://github.com/philips-labs/terraform-aws-github-runner/issues/3591)) ([1829721](https://github.com/philips-labs/terraform-aws-github-runner/commit/1829721cb647b005ca44b5feb8d0de27217e6074)) + +## [5.2.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.2.0...v5.2.1) (2023-10-31) + + +### Bug Fixes + +* shorten role name for ssm housekeeper ([#3587](https://github.com/philips-labs/terraform-aws-github-runner/issues/3587)) ([a1440b5](https://github.com/philips-labs/terraform-aws-github-runner/commit/a1440b5a1b329e65e860292895714cc3f072a1bb)) + +## [5.2.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.1.0...v5.2.0) (2023-10-30) + + +### Features + +* SSM housekeeper ([#3577](https://github.com/philips-labs/terraform-aws-github-runner/issues/3577)) ([340deea](https://github.com/philips-labs/terraform-aws-github-runner/commit/340deeaee94fa9cddbe11d9421cb06c35f2a2726)) + + +### Bug Fixes + +* allow use of associate_public_ipv4_address from top-level module ([#3572](https://github.com/philips-labs/terraform-aws-github-runner/issues/3572)) ([0ff7b23](https://github.com/philips-labs/terraform-aws-github-runner/commit/0ff7b2389fcbb607cdc37392b1612a14e9511c43)) + +## [5.1.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v5.0.0...v5.1.0) (2023-10-30) + + +### Features + +* add AMI house keeping lambda ([#3570](https://github.com/philips-labs/terraform-aws-github-runner/issues/3570)) ([87104e8](https://github.com/philips-labs/terraform-aws-github-runner/commit/87104e8c09a9aaa6069be85c9b68920e455ff715)) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3579](https://github.com/philips-labs/terraform-aws-github-runner/issues/3579)) ([ccb1d32](https://github.com/philips-labs/terraform-aws-github-runner/commit/ccb1d32be888a28d37417275950afdc01c4ac0da)) + +## [5.0.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.7.0...v5.0.0) (2023-10-27) + + +### ⚠ BREAKING CHANGES + +* remove depcrecated input and output variables ([#3567](https://github.com/philips-labs/terraform-aws-github-runner/issues/3567)) +* Change runner labels to list[string] and apply TFLint ([#3410](https://github.com/philips-labs/terraform-aws-github-runner/issues/3410)) +* replace Amazon Linux 2 by Amazon Linux 2023 as default Linux AMI ([#3437](https://github.com/philips-labs/terraform-aws-github-runner/issues/3437)) + +### Features + +* replace Amazon Linux 2 by Amazon Linux 2023 as default Linux AMI ([#3437](https://github.com/philips-labs/terraform-aws-github-runner/issues/3437)) ([35219f5](https://github.com/philips-labs/terraform-aws-github-runner/commit/35219f5b35dcdd780e1a7d3d6b109933914233da)) + + +### Bug Fixes + +* Change runner labels to list[string] and apply TFLint ([#3410](https://github.com/philips-labs/terraform-aws-github-runner/issues/3410)) ([0b398f2](https://github.com/philips-labs/terraform-aws-github-runner/commit/0b398f2f1010e0af84022a6d11d696cdcb9eb1ec)) +* remove depcrecated input and output variables ([#3567](https://github.com/philips-labs/terraform-aws-github-runner/issues/3567)) ([89c8575](https://github.com/philips-labs/terraform-aws-github-runner/commit/89c8575bf5df80c9a0861ff63e72a5762edbdcfc)) + +## [4.7.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.6.0...v4.7.0) (2023-10-26) + + +### Features + +* Add public IP association to github runner ([#3547](https://github.com/philips-labs/terraform-aws-github-runner/issues/3547)) ([1a25b2c](https://github.com/philips-labs/terraform-aws-github-runner/commit/1a25b2c6bced8ab4657ace64ef0b6694140856de)) + + +### Bug Fixes + +* add tags to aws resources ([#3549](https://github.com/philips-labs/terraform-aws-github-runner/issues/3549)) ([c747139](https://github.com/philips-labs/terraform-aws-github-runner/commit/c74713923635d51e37cca98449a396a73f71a7bc)) +* restrict runner security group to only ingress ([#3564](https://github.com/philips-labs/terraform-aws-github-runner/issues/3564)) ([e63fdc5](https://github.com/philips-labs/terraform-aws-github-runner/commit/e63fdc5ec3b85f2b1fa9a4f881588681fee0c07d)) + +## [4.6.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.5.1...v4.6.0) (2023-10-19) + + +### Features + +* Use Instance Metadata Service Version 2 by default. ([#3513](https://github.com/philips-labs/terraform-aws-github-runner/issues/3513)) ([d8d69c3](https://github.com/philips-labs/terraform-aws-github-runner/commit/d8d69c34b0492f125a9d23689e356d04021fe434)) + +## [4.5.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.5.0...v4.5.1) (2023-10-18) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3530](https://github.com/philips-labs/terraform-aws-github-runner/issues/3530)) ([0ada33b](https://github.com/philips-labs/terraform-aws-github-runner/commit/0ada33b99270da88716e7b4a381fae6d7a06fdd3)) +* **webhook:** Avoid jobs are accepted without labels ([#3548](https://github.com/philips-labs/terraform-aws-github-runner/issues/3548)) ([cb78738](https://github.com/philips-labs/terraform-aws-github-runner/commit/cb7873819b660be99b336c7ee486405b5cb3c2cb)) + +## [4.5.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.4.1...v4.5.0) (2023-10-04) + + +### Features + +* namespace EC2 tags ([#3523](https://github.com/philips-labs/terraform-aws-github-runner/issues/3523)) ([35aa73a](https://github.com/philips-labs/terraform-aws-github-runner/commit/35aa73ac1e6df30d4a5c314457da5646a117131b)) + + +### Bug Fixes + +* **lambda:** Bump @aws-lambda-powertools/logger from 1.12.1 to 1.14.0 in /lambdas ([#3521](https://github.com/philips-labs/terraform-aws-github-runner/issues/3521)) ([3f42529](https://github.com/philips-labs/terraform-aws-github-runner/commit/3f425297c4458d3dc31f45d1a22302ba39c59000)) +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3525](https://github.com/philips-labs/terraform-aws-github-runner/issues/3525)) ([1b24342](https://github.com/philips-labs/terraform-aws-github-runner/commit/1b243426fdb76fc9fff2d244df357f15bbbb7b24)) +* **lambda:** Bump the octokit group in /lambdas with 1 update ([#3519](https://github.com/philips-labs/terraform-aws-github-runner/issues/3519)) ([cde80cd](https://github.com/philips-labs/terraform-aws-github-runner/commit/cde80cd9e6144e5b6c11f055e601521f277a4932)) + +## [4.4.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.4.0...v4.4.1) (2023-09-28) + + +### Bug Fixes + +* incorrect path to update app script ([#3510](https://github.com/philips-labs/terraform-aws-github-runner/issues/3510)) ([0865273](https://github.com/philips-labs/terraform-aws-github-runner/commit/0865273c9b426ce455380b297f5a9edbf3c767f4)) + +## [4.4.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.3.0...v4.4.0) (2023-09-27) + + +### Features + +* add module to update GitHub app webhook ([#3451](https://github.com/philips-labs/terraform-aws-github-runner/issues/3451)) ([525f400](https://github.com/philips-labs/terraform-aws-github-runner/commit/525f400f663652b05273c7376734e2853fa34fa5)) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3500](https://github.com/philips-labs/terraform-aws-github-runner/issues/3500)) ([8d4e0cd](https://github.com/philips-labs/terraform-aws-github-runner/commit/8d4e0cd95ab55fa6ffad5b8a8d2a113fad75c820)) +* **lambda:** bump the octokit group in /lambdas with 2 updates ([#3501](https://github.com/philips-labs/terraform-aws-github-runner/issues/3501)) ([f0c1285](https://github.com/philips-labs/terraform-aws-github-runner/commit/f0c1285d994f79dfa5731b851ae6c7b8614bd33a)) + +## [4.3.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.2.3...v4.3.0) (2023-09-22) + + +### Features + +* Add ebs_optimized option ([#3492](https://github.com/philips-labs/terraform-aws-github-runner/issues/3492)) ([bf73f1c](https://github.com/philips-labs/terraform-aws-github-runner/commit/bf73f1ce3756ce8a964d6782373a18128903f5e1)) + + +### Bug Fixes + +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3483](https://github.com/philips-labs/terraform-aws-github-runner/issues/3483)) ([1fad99d](https://github.com/philips-labs/terraform-aws-github-runner/commit/1fad99d6df3bf8bb78d57feac08311776c60aa4f)) +* missing partion in ARN to support China or govCloud ([#3494](https://github.com/philips-labs/terraform-aws-github-runner/issues/3494)) ([b0b3df6](https://github.com/philips-labs/terraform-aws-github-runner/commit/b0b3df6d828ae239bc3fab712e5744ec7b4d2403)) + +## [4.2.3](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.2.2...v4.2.3) (2023-09-12) + + +### Bug Fixes + +* **lambda:** Bump axios from 1.4.0 to 1.5.0 in /lambdas ([#3475](https://github.com/philips-labs/terraform-aws-github-runner/issues/3475)) ([f94645b](https://github.com/philips-labs/terraform-aws-github-runner/commit/f94645b771764af4ba0f0e3e55f481c3fd5833dd)) +* **lambda:** Bump cron-parser from 4.8.1 to 4.9.0 in /lambdas ([#3474](https://github.com/philips-labs/terraform-aws-github-runner/issues/3474)) ([08dfabf](https://github.com/philips-labs/terraform-aws-github-runner/commit/08dfabf940f2fdcab3831796c2be6c2afc967fce)) +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3472](https://github.com/philips-labs/terraform-aws-github-runner/issues/3472)) ([c8245e0](https://github.com/philips-labs/terraform-aws-github-runner/commit/c8245e0eea27320e32eb5e6514e13e6d93f47b7a)) + +## [4.2.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.2.1...v4.2.2) (2023-09-06) + + +### Bug Fixes + +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3462](https://github.com/philips-labs/terraform-aws-github-runner/issues/3462)) ([a8276a4](https://github.com/philips-labs/terraform-aws-github-runner/commit/a8276a471020177e6350f000c029c3636deb68fa)) +* **lambda:** Bump typescript from 5.1.6 to 5.2.2 in /lambdas ([#3465](https://github.com/philips-labs/terraform-aws-github-runner/issues/3465)) ([026ce11](https://github.com/philips-labs/terraform-aws-github-runner/commit/026ce116907209dea96cfe3dad1413bfde4bf7bd)) + +## [4.2.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.2.0...v4.2.1) (2023-08-31) + + +### Bug Fixes + +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3455](https://github.com/philips-labs/terraform-aws-github-runner/issues/3455)) ([3fbe6d6](https://github.com/philips-labs/terraform-aws-github-runner/commit/3fbe6d6ff2a73a7194acf2b31e8efd146a9feab8)) + +## [4.2.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.1.2...v4.2.0) (2023-08-24) + + +### Features + +* support for cloudwatch config on per runner for multi-runners ([#3447](https://github.com/philips-labs/terraform-aws-github-runner/issues/3447)) ([cdaa950](https://github.com/philips-labs/terraform-aws-github-runner/commit/cdaa95057d09966c509a360fd9cea9d81a4993d9)) + +## [4.1.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.1.1...v4.1.2) (2023-08-22) + + +### Bug Fixes + +* **lambda:** Bump the aws group in /lambdas with 5 updates ([#3439](https://github.com/philips-labs/terraform-aws-github-runner/issues/3439)) ([416e52f](https://github.com/philips-labs/terraform-aws-github-runner/commit/416e52facaa0384a7662425fb87925ba4a0cf574)) +* Replace defaul AMI for WIndows ([#3445](https://github.com/philips-labs/terraform-aws-github-runner/issues/3445)) ([a590da5](https://github.com/philips-labs/terraform-aws-github-runner/commit/a590da5638db1af4ff5fe315f6ab833cc9b016c2)), closes [#3423](https://github.com/philips-labs/terraform-aws-github-runner/issues/3423) + +## [4.1.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.1.0...v4.1.1) (2023-08-16) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3425](https://github.com/philips-labs/terraform-aws-github-runner/issues/3425)) ([79983a0](https://github.com/philips-labs/terraform-aws-github-runner/commit/79983a081c11b8c6cabd33c0f01c3ace44af0c87)) +* set log retention in each module by default to 180 ([#3433](https://github.com/philips-labs/terraform-aws-github-runner/issues/3433)) ([86e6abc](https://github.com/philips-labs/terraform-aws-github-runner/commit/86e6abc174d714c0efafb25e7b8cb04d7b1e1e28)) + +## [4.1.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.0.2...v4.1.0) (2023-08-08) + + +### Features + +* **runners:** add configurable eviction strategy to idle config ([#3375](https://github.com/philips-labs/terraform-aws-github-runner/issues/3375)) ([896f473](https://github.com/philips-labs/terraform-aws-github-runner/commit/896f473107beb37468ce957825ac6de448119dbc)) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3413](https://github.com/philips-labs/terraform-aws-github-runner/issues/3413)) ([1acc8ba](https://github.com/philips-labs/terraform-aws-github-runner/commit/1acc8ba295e81c0303bbc08db864a90495a23df9)) +* **runners:** retry aws metadata token download on Linux ([#3408](https://github.com/philips-labs/terraform-aws-github-runner/issues/3408)) ([ef46827](https://github.com/philips-labs/terraform-aws-github-runner/commit/ef46827e31d3aaabfe9676df4caad756eb1f3dc8)) + +## [4.0.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.0.1...v4.0.2) (2023-08-03) + + +### Bug Fixes + +* ensure `/opt/start-runner-service.sh` is run with Bash ([1657e8e](https://github.com/philips-labs/terraform-aws-github-runner/commit/1657e8e05cd1f438b5420f89f5e0511e868047e6)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3398](https://github.com/philips-labs/terraform-aws-github-runner/issues/3398)) ([14db7ca](https://github.com/philips-labs/terraform-aws-github-runner/commit/14db7cad993a478ab42ef12deefb3286f2808468)) +* **lambda:** bump typescript from 5.0.4 to 5.1.6 in /lambdas ([#3399](https://github.com/philips-labs/terraform-aws-github-runner/issues/3399)) ([ff8af09](https://github.com/philips-labs/terraform-aws-github-runner/commit/ff8af09678ad99f8b99c7424e56f5d56cbbc0b9b)) +* **runners:** ensure `/opt/start-runner-service.sh` is run with Bash ([#3407](https://github.com/philips-labs/terraform-aws-github-runner/issues/3407)) ([1657e8e](https://github.com/philips-labs/terraform-aws-github-runner/commit/1657e8e05cd1f438b5420f89f5e0511e868047e6)) + +## [4.0.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v4.0.0...v4.0.1) (2023-07-31) + + +### Bug Fixes + +* allow disable JIT config for ephemeral runners ([#3393](https://github.com/philips-labs/terraform-aws-github-runner/issues/3393)) ([cfbcc94](https://github.com/philips-labs/terraform-aws-github-runner/commit/cfbcc944fc183b481caaee323e7832ec1964eb54)) + +## [4.0.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.6.1...v4.0.0) (2023-07-25) + + +### ⚠ BREAKING CHANGES + +* replace registration tokens by JIT config for ephemeral runners ([#3350](https://github.com/philips-labs/terraform-aws-github-runner/issues/3350)) + +### Features + +* replace registration tokens by JIT config for ephemeral runners ([#3350](https://github.com/philips-labs/terraform-aws-github-runner/issues/3350)) ([2b776ba](https://github.com/philips-labs/terraform-aws-github-runner/commit/2b776bacb306be2eb14cf20f31251eb544a3cfba)) + + +### Bug Fixes + +* **lambda:** bump the aws group in /lambdas with 3 updates ([#3381](https://github.com/philips-labs/terraform-aws-github-runner/issues/3381)) ([3af675a](https://github.com/philips-labs/terraform-aws-github-runner/commit/3af675a05ece3dd55f9680249fb8c6e3bcd51811)) +* **lambda:** bump the octokit group in /lambdas with 4 updates ([#3386](https://github.com/philips-labs/terraform-aws-github-runner/issues/3386)) ([b067138](https://github.com/philips-labs/terraform-aws-github-runner/commit/b067138bccd68ae3ee56c9b8168a6737c6cbb46b)) +* scale up lambda build issue. ([#3388](https://github.com/philips-labs/terraform-aws-github-runner/issues/3388)) ([e78232c](https://github.com/philips-labs/terraform-aws-github-runner/commit/e78232caeeeab8829c04a9785ee05ddfe07939c1)) + +## [3.6.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.6.0...v3.6.1) (2023-07-20) + + +### Bug Fixes + +* add state for multi-runner default ami-filter ([#3373](https://github.com/philips-labs/terraform-aws-github-runner/issues/3373)) ([f5b6ead](https://github.com/philips-labs/terraform-aws-github-runner/commit/f5b6eade82163373fff8ee9f4dc07242a44a3b92)) +* broken AMI fileter ([#3371](https://github.com/philips-labs/terraform-aws-github-runner/issues/3371)) ([999d139](https://github.com/philips-labs/terraform-aws-github-runner/commit/999d139c49bbce4de681d95d4462adbccec5f4fa)) +* **lambda:** bump word-wrap from 1.2.3 to 1.2.4 in /lambdas ([#3374](https://github.com/philips-labs/terraform-aws-github-runner/issues/3374)) ([c320253](https://github.com/philips-labs/terraform-aws-github-runner/commit/c320253d8cd86a5190ef67e748e7d296e03ef788)) +* merge ami filters. ([999d139](https://github.com/philips-labs/terraform-aws-github-runner/commit/999d139c49bbce4de681d95d4462adbccec5f4fa)) +* retry aws metadata token download ([#3292](https://github.com/philips-labs/terraform-aws-github-runner/issues/3292)) ([5537474](https://github.com/philips-labs/terraform-aws-github-runner/commit/553747418daaf92b6732615cdfc8df91a6295366)) + +## [3.6.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.5.0...v3.6.0) (2023-07-18) + + +### Features + +* **images:** Allow specifying temporary security group source IP for packer builds ([#3351](https://github.com/philips-labs/terraform-aws-github-runner/issues/3351)) ([6d018f6](https://github.com/philips-labs/terraform-aws-github-runner/commit/6d018f648d998342c3e01443d49b60315d6c8f7f)) +* **syncer:** update bucket policy to require ssl ([#3342](https://github.com/philips-labs/terraform-aws-github-runner/issues/3342)) ([7a3d825](https://github.com/philips-labs/terraform-aws-github-runner/commit/7a3d8256c8a28849f84516d49a44e537e77eb4f2)) +* tag runner volumes with the same tags as the instance ([#3354](https://github.com/philips-labs/terraform-aws-github-runner/issues/3354)) ([116ea58](https://github.com/philips-labs/terraform-aws-github-runner/commit/116ea580eb004d581f46e4f245a3d3409c3b7568)) +* update bucket policy to require ssl ([7a3d825](https://github.com/philips-labs/terraform-aws-github-runner/commit/7a3d8256c8a28849f84516d49a44e537e77eb4f2)) + + +### Bug Fixes + +* add more outputs to multi runners module. ([#3343](https://github.com/philips-labs/terraform-aws-github-runner/issues/3343)) ([41a74ec](https://github.com/philips-labs/terraform-aws-github-runner/commit/41a74ec6203e8a5f6af96fa7c054724108b08874)) +* Changed the ami filters to ensure that AMI is available before its used in launch template. ([#3220](https://github.com/philips-labs/terraform-aws-github-runner/issues/3220)) ([0bcfbc7](https://github.com/philips-labs/terraform-aws-github-runner/commit/0bcfbc784fd22313a36613fe1209fede8a52e254)) +* **lambda:** bump @aws-lambda-powertools/logger from 1.8.0 to 1.10.0 in /lambdas ([#3337](https://github.com/philips-labs/terraform-aws-github-runner/issues/3337)) ([708748a](https://github.com/philips-labs/terraform-aws-github-runner/commit/708748aa6e29681682ebec0efdcb28ff84c362c2)) +* **lambda:** bump semver from 5.7.1 to 5.7.2 in /lambdas ([#3359](https://github.com/philips-labs/terraform-aws-github-runner/issues/3359)) ([1279e8c](https://github.com/philips-labs/terraform-aws-github-runner/commit/1279e8cfaefe595ffefa803bd1e61cccf8075586)) +* **lambda:** bump the aws group in /lambdas with 5 updates ([#3368](https://github.com/philips-labs/terraform-aws-github-runner/issues/3368)) ([32c15ec](https://github.com/philips-labs/terraform-aws-github-runner/commit/32c15ec3cc38365224871b6806cc21f015f8f0a7)) +* **lambda:** Rename scale-down.tf service name ([#3361](https://github.com/philips-labs/terraform-aws-github-runner/issues/3361)) ([22fad41](https://github.com/philips-labs/terraform-aws-github-runner/commit/22fad412b7b91706cc3cb7b227a9d57c1d77d73a)) +* **multi-runner:** Fix runner_additional_security_group_ids ([#3352](https://github.com/philips-labs/terraform-aws-github-runner/issues/3352)) ([1f0c938](https://github.com/philips-labs/terraform-aws-github-runner/commit/1f0c938e71e3afc81921c5659cc9e6267dafdf46)) + +## [3.5.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.4.2...v3.5.0) (2023-06-21) + + +### Features +* Support AWS 5.x Terraform provider ([#3315](https://github.com/philips-labs/terraform-aws-github-runner/issues/3315)) ([d0e8960](https://github.com/philips-labs/terraform-aws-github-runner/commit/d0e89608f52ff0db4abe204af6718a73e780ea98)) + + +### Bug Fixes + +* **lambda:** bump @aws-sdk/client-ec2 from 3.352.0 to 3.356.0 in /lambdas ([#3333](https://github.com/philips-labs/terraform-aws-github-runner/issues/3333)) ([9cb0369](https://github.com/philips-labs/terraform-aws-github-runner/commit/9cb0369195855ea2e1f75f905098588101a166f8)) +* **lambda:** bump @aws-sdk/client-s3 from 3.352.0 to 3.354.0 in /lambdas ([#3329](https://github.com/philips-labs/terraform-aws-github-runner/issues/3329)) ([37acc92](https://github.com/philips-labs/terraform-aws-github-runner/commit/37acc9247526fdfbe940fca1ad19beea89f3576c)) +* **lambda:** bump @aws-sdk/client-ssm from 3.321.1 to 3.350.0 in /lambdas ([#3319](https://github.com/philips-labs/terraform-aws-github-runner/issues/3319)) ([97d5c73](https://github.com/philips-labs/terraform-aws-github-runner/commit/97d5c7384cbeec38ee0d9b16167ed4a2f883d291)) +* **lambda:** bump @aws-sdk/client-ssm from 3.352.0 to 3.354.0 in /lambdas ([#3327](https://github.com/philips-labs/terraform-aws-github-runner/issues/3327)) ([e315230](https://github.com/philips-labs/terraform-aws-github-runner/commit/e315230f42d9b321a3ba28ff7f9294fc77dec78d)) + +## [3.4.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.4.1...v3.4.2) (2023-06-13) + + +### Bug Fixes + +* Fix pool logic with runner name prefix ([#3303](https://github.com/philips-labs/terraform-aws-github-runner/issues/3303)) ([66e2a66](https://github.com/philips-labs/terraform-aws-github-runner/commit/66e2a66adcf200a85c0200382756f4fa5a71aadb)) +* remove duplicate vpc execution permissions ([#3304](https://github.com/philips-labs/terraform-aws-github-runner/issues/3304)) ([0bebeef](https://github.com/philips-labs/terraform-aws-github-runner/commit/0bebeef094b2e64af7f81166becae6c65167df86)) + +## [3.4.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.4.0...v3.4.1) (2023-05-23) + + +### Bug Fixes + +* added additional outputs to multi runner module. ([#3283](https://github.com/philips-labs/terraform-aws-github-runner/issues/3283)) ([9644e05](https://github.com/philips-labs/terraform-aws-github-runner/commit/9644e05a2345369349ee9217da47db68860997d5)) +* **lambda:** bump @aws-sdk/client-sqs from 3.321.1 to 3.332.0 in /lambdas ([#3271](https://github.com/philips-labs/terraform-aws-github-runner/issues/3271)) ([170baa8](https://github.com/philips-labs/terraform-aws-github-runner/commit/170baa8e8799a6335f4d0f868e89a8496632aa11)) +* **lambda:** bump @aws-sdk/client-sqs from 3.332.0 to 3.337.0 in /lambdas ([#3284](https://github.com/philips-labs/terraform-aws-github-runner/issues/3284)) ([01a053e](https://github.com/philips-labs/terraform-aws-github-runner/commit/01a053ee049c7a7cd80241d10272155c1a94af88)) +* **lambda:** bump @aws-sdk/lib-storage from 3.321.1 to 3.335.0 in /lambdas ([#3281](https://github.com/philips-labs/terraform-aws-github-runner/issues/3281)) ([9387bee](https://github.com/philips-labs/terraform-aws-github-runner/commit/9387bee757d7692b33a5599a6d2868de9f2ba492)) +* **lambda:** bump @aws-sdk/lib-storage from 3.335.0 to 3.337.0 in /lambdas ([#3286](https://github.com/philips-labs/terraform-aws-github-runner/issues/3286)) ([2a447ae](https://github.com/philips-labs/terraform-aws-github-runner/commit/2a447ae43520e9fca19d103ae956d5eb44e7f21a)) +* **lambda:** bump @octokit/auth-app from 4.0.9 to 4.0.13 in /lambdas ([#3287](https://github.com/philips-labs/terraform-aws-github-runner/issues/3287)) ([517d2e0](https://github.com/philips-labs/terraform-aws-github-runner/commit/517d2e02623ec863ebeb1fae105332026a32fe9e)) +* **lambda:** bump @octokit/types from 9.2.1 to 9.2.2 in /lambdas ([#3273](https://github.com/philips-labs/terraform-aws-github-runner/issues/3273)) ([e083898](https://github.com/philips-labs/terraform-aws-github-runner/commit/e083898e4da41c0c1f180094ae132479bc155ee6)) +* **multi-runner:** allow runner_additional_security_group_ids to apply to multi_runner_config ([#3221](https://github.com/philips-labs/terraform-aws-github-runner/issues/3221)) ([5fb1fa8](https://github.com/philips-labs/terraform-aws-github-runner/commit/5fb1fa87e2cec416051c225e5b32504df1e30004)) +* **multi-runner:** enable SSE by default for runner-binaries bucket ([#3274](https://github.com/philips-labs/terraform-aws-github-runner/issues/3274)) ([5d314f2](https://github.com/philips-labs/terraform-aws-github-runner/commit/5d314f2966381f6d281ef913f601f579e627f260)) +* **webhook:** logic to find the workflow labels inside runner config supported labelsets. ([#3278](https://github.com/philips-labs/terraform-aws-github-runner/issues/3278)) ([9fcf33a](https://github.com/philips-labs/terraform-aws-github-runner/commit/9fcf33a86254cf64f115327f506c940583144ed5)) + +## [3.4.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.3.0...v3.4.0) (2023-05-12) + + +### Features + +* **runners:** allow explicitly standard or unlimited ([#3244](https://github.com/philips-labs/terraform-aws-github-runner/issues/3244)) ([e2cf7ac](https://github.com/philips-labs/terraform-aws-github-runner/commit/e2cf7ace992df354281c19f8240a97c134264758)) + + +### Bug Fixes + +* Expand repository_white_list documentation ([#3254](https://github.com/philips-labs/terraform-aws-github-runner/issues/3254)) ([5f3771a](https://github.com/philips-labs/terraform-aws-github-runner/commit/5f3771af9e81f362f598fed5178e6f029fa2aa23)) +* **lambda:** bump @octokit/types from 9.2.0 to 9.2.1 in /lambdas ([#3259](https://github.com/philips-labs/terraform-aws-github-runner/issues/3259)) ([4bb77e0](https://github.com/philips-labs/terraform-aws-github-runner/commit/4bb77e062d378d52adddeb97929166d1ba9a95c4)) + +## [3.3.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.2.0...v3.3.0) (2023-05-05) + + +### Features + +* added the option to generate outputs from packer builds. ([#3246](https://github.com/philips-labs/terraform-aws-github-runner/issues/3246)) ([97c4ee7](https://github.com/philips-labs/terraform-aws-github-runner/commit/97c4ee7d1145c5f10ea01bbe4a81e1e6e827cef9)) +* **syncer:** Enable S3 bucket versioning for syncer S3 bucket ([#3108](https://github.com/philips-labs/terraform-aws-github-runner/issues/3108)) ([e679021](https://github.com/philips-labs/terraform-aws-github-runner/commit/e67902133b2ab426068964c9bc24aab6ecd37a79)) + + +### Bug Fixes + +* **lambda:** bump @octokit/types from 9.1.2 to 9.2.0 in /lambdas ([#3243](https://github.com/philips-labs/terraform-aws-github-runner/issues/3243)) ([4ff85bb](https://github.com/philips-labs/terraform-aws-github-runner/commit/4ff85bbdb7fc00b8174092ed23c2eef10842460b)) +* **lambda:** bump axios from 1.3.6 to 1.4.0 in /lambdas ([#3242](https://github.com/philips-labs/terraform-aws-github-runner/issues/3242)) ([5620d88](https://github.com/philips-labs/terraform-aws-github-runner/commit/5620d886d74423889eb13f3c1746f784fbcb36a0)) +* S3 bucket logging prefix regex ([a952b91](https://github.com/philips-labs/terraform-aws-github-runner/commit/a952b91895b6629827a5af0f54fbc5c52661e36b)) +* **syncer:** S3 bucket logging prefix variable condition ([#3251](https://github.com/philips-labs/terraform-aws-github-runner/issues/3251)) ([a952b91](https://github.com/philips-labs/terraform-aws-github-runner/commit/a952b91895b6629827a5af0f54fbc5c52661e36b)) + +## [3.2.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.2.0...v3.2.0) (2023-04-28) + + +### Features + +* **runner:** include instance type & availability zone in Github Action logs ([#3223](https://github.com/philips-labs/terraform-aws-github-runner/issues/3223)) ([775a548](https://github.com/philips-labs/terraform-aws-github-runner/commit/775a54831d31710d7c8faf38320e010807b1c828)) +* **runners:** Include instance type & availability zone in logs ([775a548](https://github.com/philips-labs/terraform-aws-github-runner/commit/775a54831d31710d7c8faf38320e010807b1c828)) + + +### Bug Fixes + +* **lambda:** bump @aws-sdk/client-ec2 from 3.319.0 to 3.322.0 in /lambdas ([#3228](https://github.com/philips-labs/terraform-aws-github-runner/issues/3228)) ([5e66d58](https://github.com/philips-labs/terraform-aws-github-runner/commit/5e66d581a04af62c247970c665c3a4c5972f0791)) +* **lambda:** bump @aws-sdk/client-s3 from 3.319.0 to 3.321.1 in /lambdas ([#3230](https://github.com/philips-labs/terraform-aws-github-runner/issues/3230)) ([42a2085](https://github.com/philips-labs/terraform-aws-github-runner/commit/42a2085af5c2b450f1f3a5383e3f55d032f11ea4)) +* **lambda:** bump @aws-sdk/client-sqs from 3.319.0 to 3.321.1 in /lambdas ([#3229](https://github.com/philips-labs/terraform-aws-github-runner/issues/3229)) ([9caa02d](https://github.com/philips-labs/terraform-aws-github-runner/commit/9caa02d997fa0a620a71a96d54f06bd3f4cc2d2e)) +* **lambda:** bump @aws-sdk/lib-storage from 3.319.0 to 3.321.1 in /lambdas ([#3227](https://github.com/philips-labs/terraform-aws-github-runner/issues/3227)) ([37e970a](https://github.com/philips-labs/terraform-aws-github-runner/commit/37e970a38dca95c974901163d7ae26312b446aba)) +* **multi-runner:** convertdistribution_bucket_name to lowercase ([#3219](https://github.com/philips-labs/terraform-aws-github-runner/issues/3219)) ([43acb08](https://github.com/philips-labs/terraform-aws-github-runner/commit/43acb08d94841ad5cdb3c3f08d078e67edcd84ea)) +* remove deprecated use of S3 ACLs ([#3222](https://github.com/philips-labs/terraform-aws-github-runner/issues/3222)) ([bf4cea8](https://github.com/philips-labs/terraform-aws-github-runner/commit/bf4cea84e9c3409dfc8b6c966c083d53444098ad)) + +## [3.2.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.2.0...v3.2.0) (2023-04-28) + + +### Features + +* **runner:** include instance type & availability zone in Github Action logs ([#3223](https://github.com/philips-labs/terraform-aws-github-runner/issues/3223)) ([775a548](https://github.com/philips-labs/terraform-aws-github-runner/commit/775a54831d31710d7c8faf38320e010807b1c828)) +* **runners:** Include instance type & availability zone in logs ([775a548](https://github.com/philips-labs/terraform-aws-github-runner/commit/775a54831d31710d7c8faf38320e010807b1c828)) + + +### Bug Fixes + +* **lambda:** bump @aws-sdk/client-ec2 from 3.319.0 to 3.322.0 in /lambdas ([#3228](https://github.com/philips-labs/terraform-aws-github-runner/issues/3228)) ([5e66d58](https://github.com/philips-labs/terraform-aws-github-runner/commit/5e66d581a04af62c247970c665c3a4c5972f0791)) +* **lambda:** bump @aws-sdk/client-s3 from 3.319.0 to 3.321.1 in /lambdas ([#3230](https://github.com/philips-labs/terraform-aws-github-runner/issues/3230)) ([42a2085](https://github.com/philips-labs/terraform-aws-github-runner/commit/42a2085af5c2b450f1f3a5383e3f55d032f11ea4)) +* **lambda:** bump @aws-sdk/client-sqs from 3.319.0 to 3.321.1 in /lambdas ([#3229](https://github.com/philips-labs/terraform-aws-github-runner/issues/3229)) ([9caa02d](https://github.com/philips-labs/terraform-aws-github-runner/commit/9caa02d997fa0a620a71a96d54f06bd3f4cc2d2e)) +* **lambda:** bump @aws-sdk/lib-storage from 3.319.0 to 3.321.1 in /lambdas ([#3227](https://github.com/philips-labs/terraform-aws-github-runner/issues/3227)) ([37e970a](https://github.com/philips-labs/terraform-aws-github-runner/commit/37e970a38dca95c974901163d7ae26312b446aba)) +* **multi-runner:** convertdistribution_bucket_name to lowercase ([#3219](https://github.com/philips-labs/terraform-aws-github-runner/issues/3219)) ([43acb08](https://github.com/philips-labs/terraform-aws-github-runner/commit/43acb08d94841ad5cdb3c3f08d078e67edcd84ea)) +* remove deprecated use of S3 ACLs ([#3222](https://github.com/philips-labs/terraform-aws-github-runner/issues/3222)) ([bf4cea8](https://github.com/philips-labs/terraform-aws-github-runner/commit/bf4cea84e9c3409dfc8b6c966c083d53444098ad)) + +## [3.2.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.1.0...v3.2.0) (2023-04-28) + + +### Features + +* **runner:** include instance type & availability zone in Github Action logs ([#3223](https://github.com/philips-labs/terraform-aws-github-runner/issues/3223)) ([775a548](https://github.com/philips-labs/terraform-aws-github-runner/commit/775a54831d31710d7c8faf38320e010807b1c828)) +* **runners:** Include instance type & availability zone in logs ([775a548](https://github.com/philips-labs/terraform-aws-github-runner/commit/775a54831d31710d7c8faf38320e010807b1c828)) + + +### Bug Fixes + +* **lambda:** bump @aws-sdk/client-ec2 from 3.319.0 to 3.322.0 in /lambdas ([#3228](https://github.com/philips-labs/terraform-aws-github-runner/issues/3228)) ([5e66d58](https://github.com/philips-labs/terraform-aws-github-runner/commit/5e66d581a04af62c247970c665c3a4c5972f0791)) +* **lambda:** bump @aws-sdk/client-s3 from 3.319.0 to 3.321.1 in /lambdas ([#3230](https://github.com/philips-labs/terraform-aws-github-runner/issues/3230)) ([42a2085](https://github.com/philips-labs/terraform-aws-github-runner/commit/42a2085af5c2b450f1f3a5383e3f55d032f11ea4)) +* **lambda:** bump @aws-sdk/client-sqs from 3.319.0 to 3.321.1 in /lambdas ([#3229](https://github.com/philips-labs/terraform-aws-github-runner/issues/3229)) ([9caa02d](https://github.com/philips-labs/terraform-aws-github-runner/commit/9caa02d997fa0a620a71a96d54f06bd3f4cc2d2e)) +* **lambda:** bump @aws-sdk/lib-storage from 3.319.0 to 3.321.1 in /lambdas ([#3227](https://github.com/philips-labs/terraform-aws-github-runner/issues/3227)) ([37e970a](https://github.com/philips-labs/terraform-aws-github-runner/commit/37e970a38dca95c974901163d7ae26312b446aba)) +* **multi-runner:** convertdistribution_bucket_name to lowercase ([#3219](https://github.com/philips-labs/terraform-aws-github-runner/issues/3219)) ([43acb08](https://github.com/philips-labs/terraform-aws-github-runner/commit/43acb08d94841ad5cdb3c3f08d078e67edcd84ea)) +* remove deprecated use of S3 ACLs ([#3222](https://github.com/philips-labs/terraform-aws-github-runner/issues/3222)) ([bf4cea8](https://github.com/philips-labs/terraform-aws-github-runner/commit/bf4cea84e9c3409dfc8b6c966c083d53444098ad)) + +## [3.1.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.0.3...v3.1.0) (2023-04-20) + + +### Features + +* **images:** automatically find latest GitHub Runner version when building images ([#3129](https://github.com/philips-labs/terraform-aws-github-runner/issues/3129)) ([da49078](https://github.com/philips-labs/terraform-aws-github-runner/commit/da49078d786cf1b5e6c7f1d053ce9bbcea7de658)) +* **lambda:** add support for X-Ray tracing ([#3142](https://github.com/philips-labs/terraform-aws-github-runner/issues/3142)) ([998a0d1](https://github.com/philips-labs/terraform-aws-github-runner/commit/998a0d1381e45a52fb909396c2317ca72edec814)) + +## [3.0.3](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.0.2...v3.0.3) (2023-04-18) + + +### Bug Fixes + +* **runners:** bump @aws-lambda-powertools/logger from 1.6.0 to 1.8.0 in /modules/runners/lambdas/runners ([#3166](https://github.com/philips-labs/terraform-aws-github-runner/issues/3166)) ([2015dcf](https://github.com/philips-labs/terraform-aws-github-runner/commit/2015dcf9b45ea7d3079daa9dc1345a03de5dee43)) +* **syncer:** bump @aws-sdk/client-s3 from 3.296.0 to 3.315.0 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#3190](https://github.com/philips-labs/terraform-aws-github-runner/issues/3190)) ([31c9987](https://github.com/philips-labs/terraform-aws-github-runner/commit/31c9987da90a1b467bb1cee9451d2bb5f9fd5241)) +* **syncer:** bump @aws-sdk/lib-storage from 3.305.0 to 3.315.0 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#3187](https://github.com/philips-labs/terraform-aws-github-runner/issues/3187)) ([88e5d5d](https://github.com/philips-labs/terraform-aws-github-runner/commit/88e5d5d364057a7527a54edf20ed15bcacbe3830)) +* **syncer:** bump axios from 1.3.4 to 1.3.5 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#3171](https://github.com/philips-labs/terraform-aws-github-runner/issues/3171)) ([b8ff326](https://github.com/philips-labs/terraform-aws-github-runner/commit/b8ff3266e03c257cdc564a296d627b60367c212b)) +* **syncer:** lowercase distribution_bucket_name ([#3194](https://github.com/philips-labs/terraform-aws-github-runner/issues/3194)) ([b75010e](https://github.com/philips-labs/terraform-aws-github-runner/commit/b75010ea8e10bb1071bbeec353ef9a384695a3bc)) +* **webhook:** bump @aws-sdk/client-sqs from 3.303.0 to 3.315.0 in /modules/webhook/lambdas/webhook ([#3192](https://github.com/philips-labs/terraform-aws-github-runner/issues/3192)) ([882f911](https://github.com/philips-labs/terraform-aws-github-runner/commit/882f911c0b3dca97e8409599e8bd2fcc7fd8bac5)) +* **webhook:** bump @aws-sdk/client-ssm from 3.306.0 to 3.315.0 in /modules/webhook/lambdas/webhook ([#3191](https://github.com/philips-labs/terraform-aws-github-runner/issues/3191)) ([8cea8af](https://github.com/philips-labs/terraform-aws-github-runner/commit/8cea8afc5316152f5b0ecdb3e94c1bc66ea37b3b)) + +## [3.0.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.0.1...v3.0.2) (2023-04-07) + + +### Bug Fixes + +* **runners:** bump cron-parser from 4.7.1 to 4.8.1 in /modules/runners/lambdas/runners ([#3154](https://github.com/philips-labs/terraform-aws-github-runner/issues/3154)) ([698b1ba](https://github.com/philips-labs/terraform-aws-github-runner/commit/698b1ba3cb675bc21fe91899474fde38576aa6e8)) +* **runners:** bump typescript from 4.9.4 to 4.9.5 in /modules/runners/lambdas/runners ([#3148](https://github.com/philips-labs/terraform-aws-github-runner/issues/3148)) ([9cfa54d](https://github.com/philips-labs/terraform-aws-github-runner/commit/9cfa54dfdaa5c8cf6d312e2b4a6ce28316d91a99)) +* **runners:** upgrade aws sdk v2 to v3 ([#3138](https://github.com/philips-labs/terraform-aws-github-runner/issues/3138)) ([48da039](https://github.com/philips-labs/terraform-aws-github-runner/commit/48da03923a74f9ff5acff44bca39d4e19bae31b3)) +* **syncer:** bump @aws-sdk/lib-storage from 3.300.0 to 3.305.0 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#3153](https://github.com/philips-labs/terraform-aws-github-runner/issues/3153)) ([ec51969](https://github.com/philips-labs/terraform-aws-github-runner/commit/ec5196986448e8ac6bfc249f82f9d32a93d40df5)) +* **webhook:** bump @aws-sdk/client-ssm from 3.294.0 to 3.306.0 in /modules/webhook/lambdas/webhook ([#3164](https://github.com/philips-labs/terraform-aws-github-runner/issues/3164)) ([e6b6eef](https://github.com/philips-labs/terraform-aws-github-runner/commit/e6b6eef28eb7d444e795537cd3a60e5e701e08f2)) + +## [3.0.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v3.0.0...v3.0.1) (2023-03-31) + + +### Bug Fixes + +* add required permission to SQS message producer ([3f1fada](https://github.com/philips-labs/terraform-aws-github-runner/commit/3f1fada5bed09993b51fae9f4b094870384d0b7f)) +* Changed windows base image. ([e3708c3](https://github.com/philips-labs/terraform-aws-github-runner/commit/e3708c3cb74918306b463dd0da94dffb1cb75be8)) +* **images:** Changed windows base image to Windows_Server-2022-English-Full-ECS_Optimize* ([#3128](https://github.com/philips-labs/terraform-aws-github-runner/issues/3128)) ([e3708c3](https://github.com/philips-labs/terraform-aws-github-runner/commit/e3708c3cb74918306b463dd0da94dffb1cb75be8)) +* **images:** wait for cloud-init to be done before updating packages ([#3132](https://github.com/philips-labs/terraform-aws-github-runner/issues/3132)) ([92dff26](https://github.com/philips-labs/terraform-aws-github-runner/commit/92dff260d45ba54fcb98e4b722af0de770aae8f6)) +* **syncer:** bump @aws-lambda-powertools/logger from 1.6.0 to 1.7.0 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#3111](https://github.com/philips-labs/terraform-aws-github-runner/issues/3111)) ([3ecb894](https://github.com/philips-labs/terraform-aws-github-runner/commit/3ecb89405a0774d51ea143e6f59aac1db75fd0da)) +* **syncer:** bump @aws-sdk/lib-storage ([b2a88d4](https://github.com/philips-labs/terraform-aws-github-runner/commit/b2a88d44680f8e05dc7bb3756f73d97975cbe753)) +* **webhook:** bump @aws-lambda-powertools/logger ([1a7b6de](https://github.com/philips-labs/terraform-aws-github-runner/commit/1a7b6de3497a6391dffe783021d0849b761ff419)) +* **webhook:** bump @aws-sdk/client-sqs from 3.296.0 to 3.303.0 in /modules/webhook/lambdas/webhook ([#3137](https://github.com/philips-labs/terraform-aws-github-runner/issues/3137)) ([9cdf359](https://github.com/philips-labs/terraform-aws-github-runner/commit/9cdf3598346341459501b798d9ce293855b7072d)) + +## [3.0.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.6.1...v3.0.0) (2023-03-22) + + +### ⚠ BREAKING CHANGES + +* replace tslog by awspowertools logging ([#3037](https://github.com/philips-labs/terraform-aws-github-runner/issues/3037)) + +### Features + +* replace tslog by awspowertools logging ([#3037](https://github.com/philips-labs/terraform-aws-github-runner/issues/3037)) ([4c3ee20](https://github.com/philips-labs/terraform-aws-github-runner/commit/4c3ee20862ed75c8af05d7dad83d8336c1ebfcf5)) + + +### Bug Fixes + +* **runners:** bump @aws-sdk/client-ssm from 3.281.0 to 3.296.0 in /modules/runners/lambdas/runners ([#3098](https://github.com/philips-labs/terraform-aws-github-runner/issues/3098)) ([4a31f7b](https://github.com/philips-labs/terraform-aws-github-runner/commit/4a31f7b81c965eac4c640545c9d7df96e1ecd829)) +* **runners:** bump @octokit/rest from 19.0.5 to 19.0.7 in /modules/runners/lambdas/runners ([#3078](https://github.com/philips-labs/terraform-aws-github-runner/issues/3078)) ([4b26cfd](https://github.com/philips-labs/terraform-aws-github-runner/commit/4b26cfd33f16ac44b3542a4acceedad00d672592)) +* **runners:** bump aws-sdk from 2.1337.0 to 2.1340.0 in /modules/runners/lambdas/runners ([#3100](https://github.com/philips-labs/terraform-aws-github-runner/issues/3100)) ([f8cac68](https://github.com/philips-labs/terraform-aws-github-runner/commit/f8cac68ba2d9fbfcaa1042f24f9f27993bf99d3c)) +* **syncer:** replaced aws-sdk v2 by aws-sdk v3 ([#3075](https://github.com/philips-labs/terraform-aws-github-runner/issues/3075)) ([ac158f6](https://github.com/philips-labs/terraform-aws-github-runner/commit/ac158f68b5cc8b024d664fee369ea18455825388)) +* **webhook:** bump @aws-sdk/client-sqs from 3.294.0 to 3.296.0 in /modules/webhook/lambdas/webhook ([#3099](https://github.com/philips-labs/terraform-aws-github-runner/issues/3099)) ([87dbdf5](https://github.com/philips-labs/terraform-aws-github-runner/commit/87dbdf5d097210bca1badcc3dbf4c8b388ad4b6d)) + +## [2.6.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.6.0...v2.6.1) (2023-03-17) + + +### Bug Fixes + +* add missing IAM permissions for runners from encrypted AMI ([#3049](https://github.com/philips-labs/terraform-aws-github-runner/issues/3049)) ([e0819f6](https://github.com/philips-labs/terraform-aws-github-runner/commit/e0819f616c3208835afc20187b8c28478cd0c5ff)) +* allow the instances to send metrics ([#3067](https://github.com/philips-labs/terraform-aws-github-runner/issues/3067)) ([55c40ff](https://github.com/philips-labs/terraform-aws-github-runner/commit/55c40ff9235451b070bdde03130af1fc0ce70590)) +* packer defintions missing required metadatatag for start script ([9c1fa8a](https://github.com/philips-labs/terraform-aws-github-runner/commit/9c1fa8aaffc2de319eab5fbc8290ed3b1220d580)) +* **runners:** bump aws-sdk from 2.1329.0 to 2.1337.0 in /modules/runners/lambdas/runners ([#3072](https://github.com/philips-labs/terraform-aws-github-runner/issues/3072)) ([0e80518](https://github.com/philips-labs/terraform-aws-github-runner/commit/0e8051816e4a3dff568a4a9ff14f6fe0a909a48f)) +* **runners:** increase the log level to WARN when using the enable_job_queued_check parameter ([#3046](https://github.com/philips-labs/terraform-aws-github-runner/issues/3046)) ([1de73bf](https://github.com/philips-labs/terraform-aws-github-runner/commit/1de73bf14c9c3898e079f3ef909d60838a7587d5)) +* **syncer:** bump axios from 1.3.3 to 1.3.4 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#3059](https://github.com/philips-labs/terraform-aws-github-runner/issues/3059)) ([fa06b30](https://github.com/philips-labs/terraform-aws-github-runner/commit/fa06b30dac859595a4b08226221e388490b6e250)) +* **webhook:** bump @aws-sdk/client-sqs from 3.279.0 to 3.293.0 in /modules/webhook/lambdas/webhook ([#3074](https://github.com/philips-labs/terraform-aws-github-runner/issues/3074)) ([5de5464](https://github.com/philips-labs/terraform-aws-github-runner/commit/5de5464a0e4aa77752f7c9e8e35e1e85d3c20943)) +* **webhook:** bump @aws-sdk/client-ssm from 3.282.0 to 3.290.0 in /modules/webhook/lambdas/webhook ([#3058](https://github.com/philips-labs/terraform-aws-github-runner/issues/3058)) ([f626c6d](https://github.com/philips-labs/terraform-aws-github-runner/commit/f626c6de9c11105ed3a7502a68e048f041072859)) + +## [2.6.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.5.0...v2.6.0) (2023-03-13) + + +### Features + +* **runners:** add option to prefix registered runners in GitHub ([#3043](https://github.com/philips-labs/terraform-aws-github-runner/issues/3043)) ([ea4e042](https://github.com/philips-labs/terraform-aws-github-runner/commit/ea4e0426cb32712cfd8235a799d19f65ca531387)) + + +### Bug Fixes + +* **syncer:** enable SSE by default for dist bucket ([#3048](https://github.com/philips-labs/terraform-aws-github-runner/issues/3048)) ([a7ad31a](https://github.com/philips-labs/terraform-aws-github-runner/commit/a7ad31af7e36c0f0158b7d44048ced697dd42734)) + +## [2.5.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.4.0...v2.5.0) (2023-03-10) + + +### Features + +* added outputs for runner log groups. ([#3044](https://github.com/philips-labs/terraform-aws-github-runner/issues/3044)) ([2f683da](https://github.com/philips-labs/terraform-aws-github-runner/commit/2f683dad0053ffc0d50f8bb860fb22e487e5c00e)) +* **runner:** allow linux starter-runner script to retrieve labels without with IMDSv2 tags option ([#2764](https://github.com/philips-labs/terraform-aws-github-runner/issues/2764)) ([0d8a74c](https://github.com/philips-labs/terraform-aws-github-runner/commit/0d8a74cb2d6eff7e91b6a1e41a58d1e08f86965f)) + + +### Bug Fixes + +* **pool:** ensure pool top up respects var.ami_id_ssm_parameter_name ([#3040](https://github.com/philips-labs/terraform-aws-github-runner/issues/3040)) ([c4ab242](https://github.com/philips-labs/terraform-aws-github-runner/commit/c4ab2428c514b1f8a48e4729e542f5e2ae4b14fa)) + +## [2.4.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.3.0...v2.4.0) (2023-03-08) + + +### Features + +* add outputs for lambda and lambda log groups ([#3033](https://github.com/philips-labs/terraform-aws-github-runner/issues/3033)) ([e1ce8be](https://github.com/philips-labs/terraform-aws-github-runner/commit/e1ce8beff74896eba5b423c7510f2569078a8c01)) +* **runners:** allow to use a shared encrypted AMI ([#2933](https://github.com/philips-labs/terraform-aws-github-runner/issues/2933)) ([5514c72](https://github.com/philips-labs/terraform-aws-github-runner/commit/5514c7246184152349e3dbfa09a41b49b1156e60)) + + +### Bug Fixes + +* **runners:** bump aws-sdk from 2.1289.0 to 2.1329.0 in /modules/runners/lambdas/runners ([#3018](https://github.com/philips-labs/terraform-aws-github-runner/issues/3018)) ([9bfcfe6](https://github.com/philips-labs/terraform-aws-github-runner/commit/9bfcfe642a1d56ded7e65c190d31539c9ccc1336)) +* **webhook:** bump @aws-sdk/client-ssm from 3.278.0 to 3.282.0 in /modules/webhook/lambdas/webhook ([#3021](https://github.com/philips-labs/terraform-aws-github-runner/issues/3021)) ([7b7c211](https://github.com/philips-labs/terraform-aws-github-runner/commit/7b7c211e15f8e5e57c2866c6a9656399fdd2305e)) + +## [2.3.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.2.2...v2.3.0) (2023-03-01) + + +### Features + +* **syncer:** add option to disable runner syncer lambda trigger ([#2986](https://github.com/philips-labs/terraform-aws-github-runner/issues/2986)) ([5eb27b0](https://github.com/philips-labs/terraform-aws-github-runner/commit/5eb27b0fcf3bf01561f7ec25cada9f9d7bb0407e)) + + +### Bug Fixes + +* **runners:** bump @aws-sdk/client-ssm from 3.272.0 to 3.281.0 in /modules/runners/lambdas/runners ([#3014](https://github.com/philips-labs/terraform-aws-github-runner/issues/3014)) ([7c390ba](https://github.com/philips-labs/terraform-aws-github-runner/commit/7c390bae884dda5155d37f34e55600c8fa9023b5)) +* **runners:** propagate var.runner_ec2_tags to EC2 volumes ([#2985](https://github.com/philips-labs/terraform-aws-github-runner/issues/2985)) ([a9b1fa8](https://github.com/philips-labs/terraform-aws-github-runner/commit/a9b1fa85475214f4d1de5fab1e070ed4fad978b0)) +* **webhook:** bump @aws-sdk/client-sqs from 3.264.0 to 3.279.0 in /modules/webhook/lambdas/webhook ([#3011](https://github.com/philips-labs/terraform-aws-github-runner/issues/3011)) ([9d1d3bd](https://github.com/philips-labs/terraform-aws-github-runner/commit/9d1d3bd89a76109176a87a234b1c19a01da7873a)) + +## [2.2.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.2.1...v2.2.2) (2023-02-24) + + +### Bug Fixes + +* **runners:** bump @aws-sdk/client-ssm from 3.245.0 to 3.272.0 in /modules/runners/lambdas/runners ([#2971](https://github.com/philips-labs/terraform-aws-github-runner/issues/2971)) ([a1c700f](https://github.com/philips-labs/terraform-aws-github-runner/commit/a1c700f00fdeae436e4e3d02740d41cab980de3b)) +* **runners:** Fix typo in .setup_info generated in start-runner.ps1. ([#2967](https://github.com/philips-labs/terraform-aws-github-runner/issues/2967)) ([e8f74bc](https://github.com/philips-labs/terraform-aws-github-runner/commit/e8f74bca0e97247845968fdd4a5bd4b707e25d73)) +* **webhook:** bump @aws-sdk/client-ssm from 3.245.0 to 3.278.0 in /modules/webhook/lambdas/webhook ([#2990](https://github.com/philips-labs/terraform-aws-github-runner/issues/2990)) ([b61c2bf](https://github.com/philips-labs/terraform-aws-github-runner/commit/b61c2bf9a5ac17a0d90e0c21f18ff949cb22f57b)) +* **webhook:** bump @octokit/rest from 19.0.5 to 19.0.7 in /modules/webhook/lambdas/webhook ([#2980](https://github.com/philips-labs/terraform-aws-github-runner/issues/2980)) ([8a5a8ae](https://github.com/philips-labs/terraform-aws-github-runner/commit/8a5a8ae69a612623496f8ee1b06126e052f86d0d)) + +## [2.2.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.2.0...v2.2.1) (2023-02-17) + + +### Bug Fixes + +* **binary-syncer:** Allow lambda inside VPC ([#2938](https://github.com/philips-labs/terraform-aws-github-runner/issues/2938)) ([4bb80be](https://github.com/philips-labs/terraform-aws-github-runner/commit/4bb80be972a3b23e2914486bef0af791dc4a0c89)) +* **runners:** bump @octokit/auth-app from 4.0.8 to 4.0.9 in /modules/runners/lambdas/runners ([#2953](https://github.com/philips-labs/terraform-aws-github-runner/issues/2953)) ([fce2a75](https://github.com/philips-labs/terraform-aws-github-runner/commit/fce2a75f364d64497f5524e7d500085ba651d53c)) +* **runners:** Fix incorrect path to SSM cloudwatch config parameter. ([8f4cc41](https://github.com/philips-labs/terraform-aws-github-runner/commit/8f4cc4187b547c8d1e00f2c445db88b477aec31b)) +* **runners:** Fix path to SSM cloudwatch config parameter on Windows ([#2922](https://github.com/philips-labs/terraform-aws-github-runner/issues/2922)) ([8f4cc41](https://github.com/philips-labs/terraform-aws-github-runner/commit/8f4cc4187b547c8d1e00f2c445db88b477aec31b)) +* **syncer:** bump axios from 1.2.2 to 1.3.3 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#2959](https://github.com/philips-labs/terraform-aws-github-runner/issues/2959)) ([1aa261e](https://github.com/philips-labs/terraform-aws-github-runner/commit/1aa261e594fe5fdef8097258be7fccb0e6e306e2)) + +## [2.2.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.1.1...v2.2.0) (2023-02-10) + + +### Features + +* Add runner logfiles to output ([#2858](https://github.com/philips-labs/terraform-aws-github-runner/issues/2858)) ([a1013e9](https://github.com/philips-labs/terraform-aws-github-runner/commit/a1013e91f0fe380ff7988e20e9efea78e73acea6)) + + +### Bug Fixes + +* Add missing entry for AWS-recommended price-capacity-optimized strategy to ProcessEnv interface ([9b8f88b](https://github.com/philips-labs/terraform-aws-github-runner/commit/9b8f88ba275cde40ce2b33ff51aae55b094928a9)) +* Adds InsufficientInstanceCapacity to list of scaling errors ([4eb3b16](https://github.com/philips-labs/terraform-aws-github-runner/commit/4eb3b16b0dfd60fafde6843fa9f8c95399db3f8b)) +* **multi-runner:** Create DLQ only if requested ([#2903](https://github.com/philips-labs/terraform-aws-github-runner/issues/2903)) ([3d33744](https://github.com/philips-labs/terraform-aws-github-runner/commit/3d337447158196e5cff5ddae78c6d867e103696d)) +* **multi-runner:** Missing ami_id_ssm_parameter_name parameter from multi-runner [#2883](https://github.com/philips-labs/terraform-aws-github-runner/issues/2883) ([#2911](https://github.com/philips-labs/terraform-aws-github-runner/issues/2911)) ([19138d9](https://github.com/philips-labs/terraform-aws-github-runner/commit/19138d9ee9d3abcf16f684782f2a51d32986d636)) +* **runner:** Adds InsufficientInstanceCapacity to list of scaling errors ([#2926](https://github.com/philips-labs/terraform-aws-github-runner/issues/2926)) ([4eb3b16](https://github.com/philips-labs/terraform-aws-github-runner/commit/4eb3b16b0dfd60fafde6843fa9f8c95399db3f8b)) +* **runners:** Add missing entry for AWS-recommended price-capacity-optimized strategy to ProcessEnv interface ([#2921](https://github.com/philips-labs/terraform-aws-github-runner/issues/2921)) ([9b8f88b](https://github.com/philips-labs/terraform-aws-github-runner/commit/9b8f88ba275cde40ce2b33ff51aae55b094928a9)) +* **runners:** Bump @octokit/types from 8.0.0 to 9.0.0 in /modules/runners/lambdas/runners ([#2910](https://github.com/philips-labs/terraform-aws-github-runner/issues/2910)) ([abdc3ac](https://github.com/philips-labs/terraform-aws-github-runner/commit/abdc3ac0fc166d58dd3a990e622c66b5e25b8e98)) +* **runners:** Bump cron-parser from 4.7.0 to 4.7.1 in /modules/runners/lambdas/runners ([#2893](https://github.com/philips-labs/terraform-aws-github-runner/issues/2893)) ([fd2dc78](https://github.com/philips-labs/terraform-aws-github-runner/commit/fd2dc78e83b15f6f6f554a1360fbd8305e0a3a2b)) +* **syncer:** bump aws-sdk from 2.1290.0 to 2.1312.0 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#2940](https://github.com/philips-labs/terraform-aws-github-runner/issues/2940)) ([8d1b281](https://github.com/philips-labs/terraform-aws-github-runner/commit/8d1b28170814cf3968d3796f954d0080923ee736)) +* **webhook:** Bump @octokit/webhooks from 10.4.0 to 10.7.0 in /modules/webhook/lambdas/webhook ([#2907](https://github.com/philips-labs/terraform-aws-github-runner/issues/2907)) ([d9ab310](https://github.com/philips-labs/terraform-aws-github-runner/commit/d9ab31051f3ccc6dceeda67038fdf47a0636445b)) + + +### Performance Improvements + +* **webhook:** Use @aws-sdk/client-sqs in the webhook Lambda ([#2924](https://github.com/philips-labs/terraform-aws-github-runner/issues/2924)) ([b8898ef](https://github.com/philips-labs/terraform-aws-github-runner/commit/b8898ef1034e06bdb01ee4f2f2215c2ec51b22c5)) + +## [2.1.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.1.0...v2.1.1) (2023-01-12) + + +### Bug Fixes + +* Honnor booting instance in runner pool ([#2801](https://github.com/philips-labs/terraform-aws-github-runner/issues/2801)) ([9f841f7](https://github.com/philips-labs/terraform-aws-github-runner/commit/9f841f7ffc0b1d3bb805bedaeb12e462eb74f835)) +* **runners:** Bump @aws-sdk/client-ssm from 3.241.0 to 3.245.0 in /modules/runners/lambdas/runners ([#2866](https://github.com/philips-labs/terraform-aws-github-runner/issues/2866)) ([ca6a0bb](https://github.com/philips-labs/terraform-aws-github-runner/commit/ca6a0bbc84d0168f9bc6dbe66a9d75de3339caf4)) +* **runners:** Bump @octokit/auth-app from 4.0.7 to 4.0.8 in /modules/runners/lambdas/runners ([#2870](https://github.com/philips-labs/terraform-aws-github-runner/issues/2870)) ([755796f](https://github.com/philips-labs/terraform-aws-github-runner/commit/755796f62a13a910e15281d08a15903df797a699)) +* **runners:** Bump luxon from 3.1.1 to 3.2.1 in /modules/runners/lambdas/runners ([#2860](https://github.com/philips-labs/terraform-aws-github-runner/issues/2860)) ([159a1ef](https://github.com/philips-labs/terraform-aws-github-runner/commit/159a1ef42e17a15907ca12a3f5fb1d9d2900f69a)) +* **syncer:** Bump aws-sdk from 2.1284.0 to 2.1290.0 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#2871](https://github.com/philips-labs/terraform-aws-github-runner/issues/2871)) ([f8c027d](https://github.com/philips-labs/terraform-aws-github-runner/commit/f8c027def8c21094a171f804cf03f832ba913ad2)) +* **webhook:** Bump @aws-sdk/client-ssm from 3.238.0 to 3.245.0 in /modules/webhook/lambdas/webhook ([#2872](https://github.com/philips-labs/terraform-aws-github-runner/issues/2872)) ([c50a773](https://github.com/philips-labs/terraform-aws-github-runner/commit/c50a773cfdeb81ad7bc39f85ea4fe075aab727ce)) +* **webhook:** Bump aws-sdk from 2.1289.0 to 2.1292.0 in /modules/webhook/lambdas/webhook ([#2876](https://github.com/philips-labs/terraform-aws-github-runner/issues/2876)) ([b3507af](https://github.com/philips-labs/terraform-aws-github-runner/commit/b3507af2f285f86e6435d43eed75c378fb8e43b9)) + +## [2.1.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.0.2...v2.1.0) (2023-01-06) + + +### Features + +* **runners:** Add delay to prevent ssm rate limits using setTimeout ([#2823](https://github.com/philips-labs/terraform-aws-github-runner/issues/2823)) ([1461efd](https://github.com/philips-labs/terraform-aws-github-runner/commit/1461efd925b1f13d0a2be7e8fc9b3fa8138d40fa)) + + +### Bug Fixes + +* Correction enable_enable_fifo_build_queue ([#2857](https://github.com/philips-labs/terraform-aws-github-runner/issues/2857)) ([455e272](https://github.com/philips-labs/terraform-aws-github-runner/commit/455e272b81052ad1b60b4d51aeeb1e6b84c5bdd2)) +* multi runner runner label ([2840d5e](https://github.com/philips-labs/terraform-aws-github-runner/commit/2840d5e8e76b7d03259027a7ea44119cc9f3ff60)) +* **runners:** Bump @aws-sdk/client-ssm from 3.238.0 to 3.241.0 in /modules/runners/lambdas/runners ([#2838](https://github.com/philips-labs/terraform-aws-github-runner/issues/2838)) ([89b1839](https://github.com/philips-labs/terraform-aws-github-runner/commit/89b18395e41d02b1ce51339cc20dad3781ab7019)) +* **runners:** Bump aws-sdk from 2.1284.0 to 2.1289.0 in /modules/runners/lambdas/runners ([#2855](https://github.com/philips-labs/terraform-aws-github-runner/issues/2855)) ([402e5ac](https://github.com/philips-labs/terraform-aws-github-runner/commit/402e5ac1515729140bc4d5c8e213219cf576c7b3)) +* Variable enable_enable_fifo_build_queue -> enable_enable_fifo_build_queue ([455e272](https://github.com/philips-labs/terraform-aws-github-runner/commit/455e272b81052ad1b60b4d51aeeb1e6b84c5bdd2)) +* **webhook:** Bump aws-sdk from 2.1284.0 to 2.1289.0 in /modules/webhook/lambdas/webhook ([#2856](https://github.com/philips-labs/terraform-aws-github-runner/issues/2856)) ([5d6dd37](https://github.com/philips-labs/terraform-aws-github-runner/commit/5d6dd3797b5dfe5374345c838bc2bfc4f2819569)) +* **webhook:** Bump axios from 1.2.1 to 1.2.2 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#2827](https://github.com/philips-labs/terraform-aws-github-runner/issues/2827)) ([686624a](https://github.com/philips-labs/terraform-aws-github-runner/commit/686624a6acb638fd62febc9b41abe67b00010a47)) + +## [2.0.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.0.1...v2.0.2) (2023-01-03) + + +### Bug Fixes + +* **runners:** Bump json5 from 2.2.1 to 2.2.3 in /modules/runners/lambdas/runners ([#2842](https://github.com/philips-labs/terraform-aws-github-runner/issues/2842)) ([d3169c2](https://github.com/philips-labs/terraform-aws-github-runner/commit/d3169c2a1c9782f408d0a2eb2a0a45e40ceb0650)) +* **syncer:** Bump json5 from 2.2.1 to 2.2.3 in /modules/runner-binaries-syncer/lambdas/runner-binaries-syncer ([#2841](https://github.com/philips-labs/terraform-aws-github-runner/issues/2841)) ([b2816f7](https://github.com/philips-labs/terraform-aws-github-runner/commit/b2816f758b364cb41bc4a1839ea188f8c0bc035e)) +* **webhook:** Bump json5 from 2.2.1 to 2.2.3 in /modules/webhook/lambdas/webhook ([#2840](https://github.com/philips-labs/terraform-aws-github-runner/issues/2840)) ([68ff414](https://github.com/philips-labs/terraform-aws-github-runner/commit/68ff4149706b6610410f398b2ceaa8d593d48544)) + +## [2.0.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v2.0.0...v2.0.1) (2023-01-03) + + +### Bug Fixes + +* Restore lost changes during merging next ([#2824](https://github.com/philips-labs/terraform-aws-github-runner/issues/2824)) ([219cb9b](https://github.com/philips-labs/terraform-aws-github-runner/commit/219cb9b55bf7300f45d6870a8dfe8ed8c799f9db)) + +## [2.0.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.18.2...v2.0.0) (2022-12-28) + +## Migrations direction +See the [GitHub release](https://github.com/philips-labs/terraform-aws-github-runner/releases/tag/v2.0.0) for migration directions + +### ⚠ BREAKING CHANGES + +* Set default lambda node runtime to 18x on arm64 ([#2763](https://github.com/philips-labs/terraform-aws-github-runner/issues/2763)) +* Drop deprecated terraform variables ([#2761](https://github.com/philips-labs/terraform-aws-github-runner/issues/2761)) +* use optional in variable block_device_mappings ([#2664](https://github.com/philips-labs/terraform-aws-github-runner/issues/2664)) +* Organise SSM paramamters by path ([#2569](https://github.com/philips-labs/terraform-aws-github-runner/issues/2569)) +* Add multi-runner capability ([#2472](https://github.com/philips-labs/terraform-aws-github-runner/issues/2472)) +* Remove old scale down mechanism (< 0.19.0) ([#2519](https://github.com/philips-labs/terraform-aws-github-runner/issues/2519)) +* Remove support check_run ([#2521](https://github.com/philips-labs/terraform-aws-github-runner/issues/2521)) + +### Features + +* Add multi-runner capability ([#2472](https://github.com/philips-labs/terraform-aws-github-runner/issues/2472)) ([fef8d65](https://github.com/philips-labs/terraform-aws-github-runner/commit/fef8d6517cb545d0909f287f23a2df665afdfc43)) +* Added publishing to workflow_job event queue for multi runner module. ([#2570](https://github.com/philips-labs/terraform-aws-github-runner/issues/2570)) ([a8b33b5](https://github.com/philips-labs/terraform-aws-github-runner/commit/a8b33b59b43d830aa96ac3d042dae088789cca10)) +* Organise SSM paramamters by path ([#2569](https://github.com/philips-labs/terraform-aws-github-runner/issues/2569)) ([b912bb8](https://github.com/philips-labs/terraform-aws-github-runner/commit/b912bb891963517cf3c102a3bb9e37e40f09497f)) +* Remove old scale down mechanism (< 0.19.0) ([#2519](https://github.com/philips-labs/terraform-aws-github-runner/issues/2519)) ([7506e9d](https://github.com/philips-labs/terraform-aws-github-runner/commit/7506e9d71e204dbb2b2a79fda5d2d50d07b96382)) +* Remove support check_run ([#2521](https://github.com/philips-labs/terraform-aws-github-runner/issues/2521)) ([4677619](https://github.com/philips-labs/terraform-aws-github-runner/commit/467761963af041b72cf10edc8a55a652311261af)) +* Set default lambda node runtime to 18x on arm64 ([#2763](https://github.com/philips-labs/terraform-aws-github-runner/issues/2763)) ([2fd1e16](https://github.com/philips-labs/terraform-aws-github-runner/commit/2fd1e163e9d11a71ffc128deb33714e505948924)) +* **webhook:** Support multiple arrays of tags is matchers. ([#2736](https://github.com/philips-labs/terraform-aws-github-runner/issues/2736)) ([d17f441](https://github.com/philips-labs/terraform-aws-github-runner/commit/d17f441c0ce115cf59cab1a8eebb679d9e4a4bdf)) + + +### Bug Fixes + +* Apply SSM changes for multi-runner ([c0051f6](https://github.com/philips-labs/terraform-aws-github-runner/commit/c0051f66f1398819c985ddef115a08a288932a17)) +* Drop deprecated terraform variables ([#2761](https://github.com/philips-labs/terraform-aws-github-runner/issues/2761)) ([955bd1d](https://github.com/philips-labs/terraform-aws-github-runner/commit/955bd1d4de50b3356ac29ac2459915fad26f1062)) +* Main module broken after supporting multiple labels ([#2802](https://github.com/philips-labs/terraform-aws-github-runner/issues/2802)) ([df054e8](https://github.com/philips-labs/terraform-aws-github-runner/commit/df054e84a27d2f72820755252bd45257433636e4)) +* Main module broken after supporting multiple labels for multi-runnes ([df054e8](https://github.com/philips-labs/terraform-aws-github-runner/commit/df054e84a27d2f72820755252bd45257433636e4)) +* **multi-runner:** Add missing default for runner_metadata_options ([#2690](https://github.com/philips-labs/terraform-aws-github-runner/issues/2690)) ([910b91c](https://github.com/philips-labs/terraform-aws-github-runner/commit/910b91c89f9a8c3fc8601773235632b663f54592)) +* **multi-runner:** Default value validation error ([#2685](https://github.com/philips-labs/terraform-aws-github-runner/issues/2685)) ([448a3a7](https://github.com/philips-labs/terraform-aws-github-runner/commit/448a3a7e25c8db8bb4f0e85b10e49c76c5c76778)) +* Multiirunner dl queue. ([#2644](https://github.com/philips-labs/terraform-aws-github-runner/issues/2644)) ([0823d47](https://github.com/philips-labs/terraform-aws-github-runner/commit/0823d47ce1988ecdb8ddb771c9c2539a7f76e0ba)) +* Remove extraneous slashes from SSM paths, other typos ([#2765](https://github.com/philips-labs/terraform-aws-github-runner/issues/2765)) ([7cdef21](https://github.com/philips-labs/terraform-aws-github-runner/commit/7cdef212c601cc8ba6ac3311b2b991852967279b)) +* **runners:** Remove Application legacy tag ([#2705](https://github.com/philips-labs/terraform-aws-github-runner/issues/2705)) ([96ced8a](https://github.com/philips-labs/terraform-aws-github-runner/commit/96ced8a11f7e8885efaf50afbcc71a50f1a8c0d4)) +* **webhook:** Add missing test dependency ([086a2e1](https://github.com/philips-labs/terraform-aws-github-runner/commit/086a2e17dc61851ecf1f3cf2bb9ce0465cd2199b)) + + +### Code Refactoring + +* use optional in variable block_device_mappings ([#2664](https://github.com/philips-labs/terraform-aws-github-runner/issues/2664)) ([08c484c](https://github.com/philips-labs/terraform-aws-github-runner/commit/08c484c3cda0bced87174857c0643eb26dc81317)) + +## [1.18.2](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.18.1...v1.18.2) (2022-12-28) + + +### Bug Fixes + +* Update dependencies ([#2804](https://github.com/philips-labs/terraform-aws-github-runner/issues/2804)) ([1cce2ab](https://github.com/philips-labs/terraform-aws-github-runner/commit/1cce2abe16284915ba88e6295448f4906eb05c56)) + +## [1.18.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.18.0...v1.18.1) (2022-12-23) + + +### Bug Fixes + +* Upgrade all non-breaking node dependencies ([#2759](https://github.com/philips-labs/terraform-aws-github-runner/issues/2759)) ([801e01f](https://github.com/philips-labs/terraform-aws-github-runner/commit/801e01f290407975aea11b85e44ac9743f9173cb)) + +## [1.18.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.17.0...v1.18.0) (2022-12-09) + + +### Features + +* Support price-capacity-optimized strategy ([#2718](https://github.com/philips-labs/terraform-aws-github-runner/issues/2718)) ([ef08afb](https://github.com/philips-labs/terraform-aws-github-runner/commit/ef08afb2b5594b9f60b15dbb60687ba91c27d668)) + + +### Bug Fixes + +* added permissions for lambda to attach lambda to the VPC. ([#2734](https://github.com/philips-labs/terraform-aws-github-runner/issues/2734)) ([fb72ee8](https://github.com/philips-labs/terraform-aws-github-runner/commit/fb72ee8f6751ebe22f7453a58373f4a983b7ba3c)) + +## [1.17.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.16.1...v1.17.0) (2022-11-30) + + +### Features + +* **runners:** Namespace `Application` tag ([#2182](https://github.com/philips-labs/terraform-aws-github-runner/issues/2182)) ([a1a47a4](https://github.com/philips-labs/terraform-aws-github-runner/commit/a1a47a4a18fe500ea58481dd29cbd95ce45c9bb5)) + + +### Bug Fixes + +* Adding missing input lambda vpc vars to syncer module ([#2701](https://github.com/philips-labs/terraform-aws-github-runner/issues/2701)) ([c91a96b](https://github.com/philips-labs/terraform-aws-github-runner/commit/c91a96bcc95defa0dc1e6bff71b3f607b5523bb5)) + +## [1.16.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.16.0...v1.16.1) (2022-11-18) + + +### Bug Fixes + +* added runner labels to output. ([#2669](https://github.com/philips-labs/terraform-aws-github-runner/issues/2669)) ([4726c1a](https://github.com/philips-labs/terraform-aws-github-runner/commit/4726c1a2bd074e4018e2b9d0652a8ce1881ae0aa)) + +## [1.16.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.15.1...v1.16.0) (2022-11-18) + + +### Features + +* Added runner labels as output. ([a3b1133](https://github.com/philips-labs/terraform-aws-github-runner/commit/a3b113359ca8c90d6f35552f436b9047f2972066)) + +## [1.15.1](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.15.0...v1.15.1) (2022-11-17) + + +### Bug Fixes + +* Updated the fifo flag for deadletter queue. ([#2641](https://github.com/philips-labs/terraform-aws-github-runner/issues/2641)) ([a8b1645](https://github.com/philips-labs/terraform-aws-github-runner/commit/a8b1645bea0d5ef05f5eb65651eeea99bcf49ade)) + +## [1.15.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.14.0...v1.15.0) (2022-11-08) + + +### Features + +* Allow to toggle access to EC2 instance tags ([#2592](https://github.com/philips-labs/terraform-aws-github-runner/issues/2592)) ([55fba22](https://github.com/philips-labs/terraform-aws-github-runner/commit/55fba22474fa802f781d46e5f3e1513c354d3a38)) + + +### Bug Fixes + +* Use aws_partition for govcloud users in ami_id_ssm_parameter_read policy definition ([#2614](https://github.com/philips-labs/terraform-aws-github-runner/issues/2614)) ([7ac65e5](https://github.com/philips-labs/terraform-aws-github-runner/commit/7ac65e589b1283f832bbe7e1264a45e00e9c8340)) + +## [1.14.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.13.0...v1.14.0) (2022-10-31) + + +### Features + +* Experimental feature - Duplicate workflow job event to extra queue ([#2268](https://github.com/philips-labs/terraform-aws-github-runner/issues/2268)) ([ac046b8](https://github.com/philips-labs/terraform-aws-github-runner/commit/ac046b8eb2a0d2d5e2219ae9ee0023fd8bdf7460)) +* **runners:** Add support for looking up runner AMI ID from an SSM parameter at instance launch time ([#2520](https://github.com/philips-labs/terraform-aws-github-runner/issues/2520)) ([68e2381](https://github.com/philips-labs/terraform-aws-github-runner/commit/68e238196877896332d36e264a64ca61a0af7ade)) + + +### Bug Fixes + +* replacing deprecated set-output in workflow ([#2564](https://github.com/philips-labs/terraform-aws-github-runner/issues/2564)) ([aa0afdd](https://github.com/philips-labs/terraform-aws-github-runner/commit/aa0afddda56ab92e37fc20b5a4448cc999786023)) + +## [1.13.0](https://github.com/philips-labs/terraform-aws-github-runner/compare/v1.12.0...v1.13.0) (2022-10-14) ### Features @@ -708,7 +1704,7 @@ - Fix missing permissions for CloudWatch Agent #445 @bennettp123 - Swap scale up/scale down timeout description #468 @jonico - Fix for invalid configuration #466 @jonico -- Add ssm:GetParameter to runner-ssm-parameters #446 @bennettp123 +- Add ssm:GetParameter to runner-ssm-parameters #446 @bennettp123 - Replace crypto #429 - Scale up lambda deprecated attribute #410 @@ -745,17 +1741,17 @@ terraform state rm $RESOURCE ### Added - Allow operator to pass in a list of managed IAM policy ARNs for the runner role #361 @jpalomaki -- expand options for sourcing lambda to include S3 #292 @eky5006 +- expand options for sourcing lambda to include S3 #292 @eky5006 ## [0.6.0] - 2020-10-10 ### Added -- Only allow tagging and termination of runner instances #201 @jpalomaki +- Only allow tagging and termination of runner instances #201 @jpalomaki ### Fixed -- Fix pagination with listing self-hosted runners #202 @HenryNguyen5 +- Fix pagination with listing self-hosted runners #202 @HenryNguyen5 ## [0.5.0] - 2020-08-25 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b74c319d5e..7122f7d930 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,9 +51,9 @@ If your issue appears to be a bug, and hasn't been reported, open a new issue. H **If you get help, help others. Good karma rulez!** -### Submitting a Merge Request +### Submitting a Pull Request -Before you submit your merge request consider the following guidelines: +Before you submit your pull request consider the following guidelines: * Make your changes in a new git branch: @@ -62,9 +62,17 @@ Before you submit your merge request consider the following guidelines: ``` * Create your patch, **including appropriate test cases**. -* Install [Terraform](https://www.terraform.io/). We lock the version with [tvenv](https://github.com/tfutils/tfenv), check `required_version` in `versions.tf` for the current development version of the module. -* Install [pre-commit hooks](https://pre-commit.com/). The hooks runs some basic checks and update the docs. The commit will run the hooks, you can invoke the hooks manually `pre-commit run --all-files` as well. -* Commit your changes using a descriptive commit message. +* Install [Terraform](https://www.terraform.io/). We lock the version with [tfenv](https://github.com/tfutils/tfenv), check `required_version` in `versions.tf` for the current development version of the module. +* Install [pre-commit hooks](https://pre-commit.com/). The hooks runs some basic checks. The commit will run the hooks, you can invoke the hooks manually `pre-commit run --all-files` as well. The hooks require tflint to be installed and terraform modules to be initialized. + * Install [tflint](https://github.com/terraform-linters/tflint). We use tflint to lint the terraform code. + * Initialize the terraform modules: + + ```shell + terraform init + ``` + +* For updating docs, you have to enable GitHub actions on your forked repository. Simply go to the tab Actions and enable actions. +* Commit your changes using a descriptive commit message: ```shell git commit -a @@ -72,7 +80,19 @@ Before you submit your merge request consider the following guidelines: Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. +* Install [node](https://nodejs.org/en/) and [yarn](https://yarnpkg.com/). We use yarn to lint, test and build the lambdas. * Build your changes locally to ensure all the tests pass: + + ```shell + cd lambdas + yarn install + yarn format + yarn lint + yarn test + yarn build + cd .. + ``` + * Push your branch to Github: ```shell @@ -137,4 +157,4 @@ Use the badge to sign-up. [contribute]: CONTRIBUTING.md [github]: https://github.com/philips-labs/terraform-aws-github-runner/issues -[slack]: https://philips-software.slack.com/home +[slack]: https://join.slack.com/t/philips-software/shared_invite/zt-xecw65v5-i1531hGP~mdVwgxLFx7ckg diff --git a/README.md b/README.md index 9f9aa9baed..67d658a6f0 100644 --- a/README.md +++ b/README.md @@ -1,408 +1,104 @@ -# Terraform module for scalable self hosted GitHub action runners +# Terraform module Self-Hosted Scalable GitHub Actions runners on AWS. -[![awesome-runners](https://img.shields.io/badge/listed%20on-awesome--runners-blue.svg)](https://github.com/jonico/awesome-runners)[![Terraform registry](https://img.shields.io/github/v/release/philips-labs/terraform-aws-github-runner?label=Terraform%20Registry)](https://registry.terraform.io/modules/philips-labs/github-runner/aws/) ![Terraform checks](https://github.com/philips-labs/terraform-aws-github-runner/workflows/Terraform%20root%20module%20checks/badge.svg) ![Lambda Webhook](https://github.com/philips-labs/terraform-aws-github-runner/workflows/Lambda%20Agent%20Webhook/badge.svg) ![Lambda Runners](https://github.com/philips-labs/terraform-aws-github-runner/workflows/Lambda%20Runners/badge.svg) ![Lambda Syncer](https://github.com/philips-labs/terraform-aws-github-runner/workflows/Lambda%20Runner%20Binaries%20Syncer/badge.svg) +[![docs](https://img.shields.io/badge/docs-runners-blue.svg)](https://philips-labs.github.io/terraform-aws-github-runner) [![awesome-runners](https://img.shields.io/badge/listed%20on-awesome--runners-blue.svg)](https://github.com/jonico/awesome-runners) [![Terraform registry](https://img.shields.io/github/v/release/philips-labs/terraform-aws-github-runner?label=Terraform%20Registry)](https://registry.terraform.io/modules/philips-labs/github-runner/aws/) [![Terraform checks](https://github.com/philips-labs/terraform-aws-github-runner/actions/workflows/terraform.yml/badge.svg)](https://github.com/philips-labs/terraform-aws-github-runner/actions/workflows/terraform.yml) [![Lambdas](https://github.com/philips-labs/terraform-aws-github-runner/actions/workflows/lambda.yml/badge.svg)](https://github.com/philips-labs/terraform-aws-github-runner/actions/workflows/lambda.yml) -This [Terraform](https://www.terraform.io/) module creates the required infrastructure needed to host [GitHub Actions](https://github.com/features/actions) self-hosted, auto-scaling runners on [AWS spot instances](https://aws.amazon.com/ec2/spot/). It provides the required logic to handle the life cycle for scaling up and down using a set of AWS Lambda functions. Runners are scaled down to zero to avoid costs when no workflows are active. - -> 📢 [Upcoming v2](https://github.com/philips-labs/terraform-aws-github-runner/issues/2517): We are busy with merging `next` back in to `main`. From that moment on we will not actively support v1. We will maintain for some moment a `v1` branch. Default PR's will go only back into main (`v2`). In case you woul like to get work explicit back in `v1` consider a PR to `v1`. - -> 📢 The branch `develop` is not used anymore, we have set the `main` branch as the default branch. Please ensure your open pull request are rebased against `main`. - -> 📢 HELP WANTED: We are running the AWS self-hosted GitHub runners OS project in Philips Labs for over two years! And we are incredibly happy with all the feedback and contribution of the open-source community. In the next months we will speak at some conferences to share the solution and story of running this open-source project. Via [this questionaire](https://forms.office.com/r/j03CUzdLFp) we would like to gather feedback from the community to use in our talks. - -- [Motivation](#motivation) -- [Overview](#overview) - - [Major configuration options.](#major-configuration-options) - - [ARM64 support via Graviton/Graviton2 instance-types](#arm64-support-via-gravitongraviton2-instance-types) -- [Usages](#usages) - - [Setup GitHub App (part 1)](#setup-github-app-part-1) - - [Setup terraform module](#setup-terraform-module) - - [Setup the webhook / GitHub App (part 2)](#setup-the-webhook--github-app-part-2) - - [Option 1: Webhook](#option-1-webhook) - - [Option 2: App](#option-2-app) - - [Install app](#install-app) - - [Encryption](#encryption) - - [Pool](#pool) - - [Idle runners](#idle-runners) - - [Ephemeral runners](#ephemeral-runners) - - [Prebuilt Images](#prebuilt-images) - - [Experimental - Optional queue to publish GitHub workflow job events](#experimental---optional-queue-to-publish-github-workflow-job-events) -- [Examples](#examples) -- [Sub modules](#sub-modules) - - [ARM64 configuration for submodules](#arm64-configuration-for-submodules) -- [Debugging](#debugging) -- [Security Consideration](#security-consideration) -- [Requirements](#requirements) -- [Providers](#providers) -- [Modules](#modules) -- [Resources](#resources) -- [Inputs](#inputs) -- [Outputs](#outputs) -- [Contribution](#contribution) -- [Philips Forest](#philips-forest) - -## Motivation - -GitHub Actions `self-hosted` runners provide a flexible option to run CI workloads on the infrastructure of your choice. Currently, no option is provided to automate the creation and scaling of action runners. This module creates the AWS infrastructure to host action runners on spot instances. It provides lambda modules to orchestrate the life cycle of the action runners. - -Lambda is chosen as the runtime for two major reasons. First, it allows the creation of small components with minimal access to AWS and GitHub. Secondly, it provides a scalable setup with minimal costs that works on repo level and scales to organization level. The lambdas will create Linux based EC2 instances with Docker to serve CI workloads that can run on Linux and/or Docker. The main goal is to support Docker-based workloads. - -A logical question would be, why not Kubernetes? In the current approach, we stay close to how the GitHub action runners are available today. The approach is to install the runner on a host where the required software is available. With this setup, we stay quite close to the current GitHub approach. Another logical choice would be AWS Auto Scaling groups. However, this choice would typically require much more permissions on instance level to GitHub. And besides that, scaling up and down is not trivial. - -## Overview - -The moment a GitHub action workflow requiring a `self-hosted` runner is triggered, GitHub will try to find a runner which can execute the workload. This module reacts to GitHub's [`check_run` event](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#check_run) or [`workflow_job` event](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#workflow_job) for the triggered workflow and creates a new runner if necessary. - -For receiving the `check_run` or `workflow_job` event by the webhook (lambda), a webhook needs to be created in GitHub. The `workflow_job` is the preferred option, and the `check_run` option will be maintained for backward compatibility. The advantage of the `workflow_job` event is that the runner checks if the received event can run on the configured runners by matching the labels, which avoid instances being scaled up and never used. The following options are available: - -- `workflow_job`: **(preferred option)** create a webhook on enterprise, org or app level. Select this option for ephemeral runners. -- `check_run`: create a webhook on enterprise, org, repo or app level. When using the app option, the app needs to be installed to repo's are using the self-hosted runners. -- a Webhook needs to be created. The webhook hook can be defined on enterprise, org, repo, or app level. - -In AWS a [API gateway](https://docs.aws.amazon.com/apigateway/index.html) endpoint is created that is able to receive the GitHub webhook events via HTTP post. The gateway triggers the webhook lambda which will verify the signature of the event. This check guarantees the event is sent by the GitHub App. The lambda only handles `workflow_job` or `check_run` events with status `queued` and matching the runner labels (only for `workflow_job`). The accepted events are posted on a SQS queue. Messages on this queue will be delayed for a configurable amount of seconds (default 30 seconds) to give the available runners time to pick up this build. - -The "scale up runner" lambda listens to the SQS queue and picks up events. The lambda runs various checks to decide whether a new EC2 spot instance needs to be created. For example, the instance is not created if the build is already started by an existing runner, or the maximum number of runners is reached. - -The Lambda first requests a registration token from GitHub, which is needed later by the runner to register itself. This avoids that the EC2 instance, which later in the process will install the agent, needs administration permissions to register the runner. Next, the EC2 spot instance is created via the launch template. The launch template defines the specifications of the required instance and contains a [`user_data`](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) script. This script will install the required software and configure it. The registration token for the action runner is stored in the parameter store (SSM), from which the user data script will fetch it and delete it once it has been retrieved. Once the user data script is finished, the action runner should be online, and the workflow will start in seconds. - -Scaling down the runners is at the moment brute-forced, every configurable amount of minutes a lambda will check every runner (instance) if it is busy. In case the runner is not busy it will be removed from GitHub and the instance terminated in AWS. At the moment there seems no other option to scale down more smoothly. - -Downloading the GitHub Action Runner distribution can be occasionally slow (more than 10 minutes). Therefore a lambda is introduced that synchronizes the action runner binary from GitHub to an S3 bucket. The EC2 instance will fetch the distribution from the S3 bucket instead of the internet. - -Secrets and private keys are stored in SSM Parameter Store. These values are encrypted using the default KMS key for SSM or passing in a custom KMS key. - -![Architecture](docs/component-overview.svg) - -Permission are managed on several places. Below the most important ones. For details check the Terraform sources. - -- The GitHub App requires access to actions and publish `workflow_job` events to the AWS webhook (API gateway). -- The scale up lambda should have access to EC2 for creating and tagging instances. -- The scale down lambda should have access to EC2 to terminate instances. - -Besides these permissions, the lambdas also need permission to CloudWatch (for logging and scheduling), SSM and S3. For more details about the required permissions see the [documentation](./modules/setup-iam-permissions/README.md) of the IAM module which uses permission boundaries. - -### Major configuration options. - -To be able to support a number of use-cases the module has quite a lot of configuration options. We try to choose reasonable defaults. The several examples also show for the main cases how to configure the runners. - -- Org vs Repo level. You can configure the module to connect the runners in GitHub on an org level and share the runners in your org. Or set the runners on repo level and the module will install the runner to the repo. There can be multiple repos but runners are not shared between repos. -- Checkrun vs Workflow job event. You can configure the webhook in GitHub to send checkrun or workflow job events to the webhook. Workflow job events are introduced by GitHub in September 2021 and are designed to support scalable runners. We advise when possible using the workflow job event, you can set `runner_enable_workflow_job_labels_check = true` to let the webhook only accept jobs based on the labels configured. The webhook will check the custom labels provided via the variable `runner_extra_labels` and the GitHub managed labels, "self-hosted", OS and architecture. The OS and architecture are derived from the settings. By default the check is disabled. -- Linux vs Windows. you can configure the OS types linux and win. Linux will be used by default. -- Re-use vs Ephemeral. By default runners are re-used for till detected idle. Once idle they will be removed from the pool. To improve security we are introducing ephemeral runners. Those runners are only used for one job. Ephemeral runners are only working in combination with the workflow job event. We also suggest using a pre-build AMI to improve the start time of jobs. -- GitHub Cloud vs GitHub Enterprise Server (GHES). The runner support GitHub Cloud as well GitHub Enterprise Server. For GHES we rely on our community to test and support. We have no possibility to test ourselves on GHES. -- Spot vs on-demand. The runners use either the EC2 spot or on-demand life cycle. Runners will be created via the AWS [CreateFleet API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html). The module (scale up lambda) will request via the CreateFleet API to create instances in one of the subnets and of the specified instance types. - - -#### ARM64 support via Graviton/Graviton2 instance-types - -When using the default example or top-level module, specifying `instance_types` that match a Graviton/Graviton 2 (ARM64) architecture (e.g. a1, t4g or any 6th-gen `g` or `gd` type), you must also specify `runner_architecture = "arm64"` and the sub-modules will be automatically configured to provision with ARM64 AMIs and leverage GitHub's ARM64 action runner. See below for more details. - -## Usages - -Examples are provided in [the example directory](examples/). Please ensure you have installed the following tools. - -- Terraform, or [tfenv](https://github.com/tfutils/tfenv). -- Bash shell or compatible -- Docker (optional, to build lambdas without node). -- AWS cli (optional) -- Node and yarn (for lambda development). - -The module supports two main scenarios for creating runners. On repository level a runner will be dedicated to only one repository, no other repository can use the runner. On organization level you can use the runner(s) for all the repositories within the organization. See [GitHub self-hosted runner instructions](https://help.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) for more information. Before starting the deployment you have to choose one option. - -The setup consists of running Terraform to create all AWS resources and manually configuring the GitHub App. The Terraform module requires configuration from the GitHub App and the GitHub app requires output from Terraform. Therefore you first create the GitHub App and configure the basics, then run Terraform, and afterwards finalize the configuration of the GitHub App. - -### Setup GitHub App (part 1) - -Go to GitHub and [create a new app](https://docs.github.com/en/developers/apps/creating-a-github-app). Beware you can create apps for your organization or for a user. For now we support only organization level apps. - -1. Create app in Github -2. Choose a name -3. Choose a website (mandatory, not required for the module). -4. Disable the webhook for now (we will configure this later or create an alternative webhook). -5. Permissions for all runners: - - Repository: - - `Actions`: Read-only (check for queued jobs) - - `Checks`: Read-only (receive events for new builds) - - `Metadata`: Read-only (default/required) -6. _Permissions for repo level runners only_: - - Repository: - - `Administration`: Read & write (to register runner) -7. _Permissions for organization level runners only_: - - Organization - - `Self-hosted runners`: Read & write (to register runner) -8. Save the new app. -9. On the General page, make a note of the "App ID" and "Client ID" parameters. -10. Generate a new private key and save the `app.private-key.pem` file. - -### Setup terraform module - -#### Download lambdas - -To apply the terraform module, the compiled lambdas (.zip files) need to be available either locally or in an S3 bucket. They can be either downloaded from the GitHub release page or build locally. - -To read the files from S3, set the `lambda_s3_bucket` variable and the specific object key for each lambda. - -The lambdas can be downloaded manually from the [release page](https://github.com/philips-labs/terraform-aws-github-runner/releases) or using the [download-lambda](./modules/download-lambda) terraform module (requires `curl` to be installed on your machine). In the `download-lambda` directory, run `terraform init && terraform apply`. The lambdas will be saved to the same directory. - -For local development you can build all the lambdas at once using `.ci/build.sh` or individually using `yarn dist`. - -#### Service-linked role - -To create spot instances the `AWSServiceRoleForEC2Spot` role needs to be added to your account. You can do that manually by following the [AWS docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#service-linked-roles-spot-instance-requests). To use terraform for creating the role, either add the following resource or let the module manage the service linked role by setting `create_service_linked_role_spot` to `true`. Be aware this is an account global role, so maybe you don't want to manage it via a specific deployment. - -```hcl -resource "aws_iam_service_linked_role" "spot" { - aws_service_name = "spot.amazonaws.com" -} -``` - -#### Terraform module - -Next create a second terraform workspace and initiate the module, or adapt one of the [examples](./examples). - -Note that `github_app.key_base64` needs to be a base64-encoded string of the `.pem` file i.e. the output of `base64 app.private-key.pem`. The decoded string can either be a multiline value or a single line value with new lines represented with literal `\n` characters. - -```hcl -module "github-runner" { - source = "philips-labs/github-runner/aws" - version = "REPLACE_WITH_VERSION" - - aws_region = "eu-west-1" - vpc_id = "vpc-123" - subnet_ids = ["subnet-123", "subnet-456"] - - prefix = "gh-ci" - - github_app = { - key_base64 = "base64string" - id = "1" - webhook_secret = "webhook_secret" - } - - webhook_lambda_zip = "lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "lambdas-download/runners.zip" - enable_organization_runners = true -} -``` - -Run terraform by using the following commands - -```bash -terraform init -terraform apply -``` - -The terraform output displays the API gateway url (endpoint) and secret, which you need in the next step. - -The lambda for syncing the GitHub distribution to S3 is triggered via CloudWatch (by default once per hour). After deployment the function is triggered via S3 to ensure the distribution is cached. - -### Setup the webhook / GitHub App (part 2) - -At this point you have 2 options. Either create a separate webhook (enterprise, -org, or repo), or create webhook in the App. - -#### Option 1: Webhook - -1. Create a new webhook on repo level for repo level for repo level runner, or org (or enterprise level) for an org level runner. -2. Provide the webhook url, should be part of the output of terraform. -3. Provide the webhook secret (`terraform output -raw `). -4. Ensure content type as `application/json`. -5. In the "Permissions & Events" section and then "Subscribe to Events" subsection, check either "Workflow Job" or "Check Run" (choose only 1 option!!!). -6. In the "Install App" section, install the App in your organization, either in all or in selected repositories. - -#### Option 2: App - -Go back to the GitHub App and update the following settings. +> 📄 Extensive documentation is available via our [GitHub Pages Docs site](https://philips-labs.github.io/terraform-aws-github-runner/). -1. Enable the webhook. -2. Provide the webhook url, should be part of the output of terraform. -3. Provide the webhook secret (`terraform output -raw `). -4. In the "Permissions & Events" section and then "Subscribe to Events" subsection, check either "Workflow Job" or "Check Run" (choose only 1 option!!!). +> 📢 We maintain the project as a truly open-source project. We maintain the project on a best effort basis. We welcome contributions from the community. Feel free to help us answering issues, reviewing PRs, or maintaining and improving the project. -#### Install app +> 📢 [`v5`](https://github.com/philips-labs/terraform-aws-github-runner/pull/3552) replaces Amazon Linux 2 with Amazon Linux 2023 as default OS. Check the PR for more details and other changes. -Finally you need to ensure the app is installed to all or selected repositories. +> 📢 For contributions to older versions you can make a PR to the related branch, e.g. `v4`. We have no release process in place for older versions. -Go back to the GitHub App and update the following settings. - -1. In the "Install App" section, install the App in your organization, either in all or in selected repositories. - -### Encryption - -The module support 2 scenarios to manage environment secrets and private key of the Lambda functions. - -#### Encrypted via a module managed KMS key (default) - -This is the default, no additional configuration is required. - -#### Encrypted via a provided KMS key - -You have to create and configure you KMS key. The module will use the context with key: `Environment` and value `var.environment` as encryption context. - -```hcl -resource "aws_kms_key" "github" { - is_enabled = true -} - -module "runners" { - - ... - kms_key_arn = aws_kms_key.github.arn - ... -``` - -### Pool - -The module basically supports two options for keeping a pool of runners. One is via a pool which only supports org-level runners, the second option is [keeping runners idle](#idle-runners). - -The pool is introduced in combination with the ephemeral runners and is primary meant to ensure if any event is unexpected dropped, and no runner was created the pool can pick up the job. The pool is maintained by a lambda. Each time the lambda is triggered a check is preformed if the number of idler runners managed by the module are meeting the expected pool size. If not, the pool will be adjusted. Keep in mind that the scale down function is still active and will terminate instances that are detected as idle. - -```hcl -pool_runner_owner = "my-org" # Org to which the runners are added -pool_config = [{ - size = 20 # size of the pool - schedule_expression = "cron(* * * * ? *)" # cron expression to trigger the adjustment of the pool -}] -``` - -The pool is NOT enabled by default and can be enabled by setting at least one object of the pool config list. The [ephemeral example](./examples/ephemeral/README.md) contains configuration options (commented out). - -### Idle runners +This [Terraform](https://www.terraform.io/) module creates the required infrastructure needed to host [GitHub Actions](https://github.com/features/actions) self-hosted, auto-scaling runners on [AWS spot instances](https://aws.amazon.com/ec2/spot/). It provides the required logic to handle the life cycle for scaling up and down using a set of AWS Lambda functions. Runners are scaled down to zero to avoid costs when no workflows are active. -The module will scale down to zero runners by default. By specifying a `idle_config` config, idle runners can be kept active. The scale down lambda checks if any of the cron expressions matches the current time with a margin of 5 seconds. When there is a match, the number of runners specified in the idle config will be kept active. In case multiple cron expressions matches, only the first one is taken into account. Below is an idle configuration for keeping runners active from 9 to 5 on working days. + + + + Runners overview + -```hcl -idle_config = [{ - cron = "* * 9-17 * * 1-5" - timeZone = "Europe/Amsterdam" - idleCount = 2 -}] -``` +## Features -_**Note**_: When using Windows runners it's recommended to keep a few runners warmed up due to the minutes-long cold start time. +- Scaling: Scale up and down based on GitHub events +- Sustainability: Scale down to zero when no jobs are running +- Security: Runners are created on-demand and terminated after use (ephemeral runners) +- Cost optimization: Runners are created on spot instances +- Tailored software, hardware and network configuration: Bring your own AMI, define the instance types and subnets to use. +- OS support: Linux (x64/arm64) and Windows +- Multi-Runner: Create multiple runner configurations with a single deployment +- GitHub cloud and GitHub Enterprise Server (GHES) support. +- Org and repo level runners. enterprise level runners are not supported (yet). -#### Supported config +## Getting started -Cron expressions are parsed by [cron-parser](https://github.com/harrisiirak/cron-parser#readme). The supported syntax. - -```bash -* * * * * * -┬ ┬ ┬ ┬ ┬ ┬ -│ │ │ │ │ | -│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun) -│ │ │ │ └───── month (1 - 12) -│ │ │ └────────── day of month (1 - 31) -│ │ └─────────────── hour (0 - 23) -│ └──────────────────── minute (0 - 59) -└───────────────────────── second (0 - 59, optional) -``` +Check out the detailed instructions in the [Getting Started](https://philips-labs.github.io/terraform-aws-github-runner/getting-started/) section of the docs. On a high level, the following steps are required to get started: +- Setup your AWS account +- Create and configure a GitHub App +- Download or build the required lambdas +- Deploy the module using Terraform +- Install the GitHub App to your organization or repositories and add your repositories to the runner group(s). -For time zones please check [TZ database name column](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the supported values. +Check out the provided Terraform examples in the [examples](./examples) directory for different scenarios. -### Ephemeral runners +## Configuration -You can configure runners to be ephemeral, runners will be used only for one job. The feature should be used in conjunction with listening for the workflow job event. Please consider the following: +Please check the [configuration](https://philips-labs.github.io/terraform-aws-github-runner/configuration/) section of the docs for major configuration options. See the Terraform module documentation for all available options. -- The scale down lambda is still active, and should only remove orphan instances. But there is no strict check in place. So ensure you configure the `minimum_running_time_in_minutes` to a value that is high enough to got your runner booted and connected to avoid it got terminated before executing a job. -- The messages sent from the webhook lambda to scale-up lambda are by default delayed delayed by SQS, to give available runners to option to start the job before the decision is made to scale more runners. For ephemeral runners there is no need to wait. Set `delay_webhook_event` to `0`. -- All events on the queue will lead to a new runner crated by the lambda. By setting `enable_job_queued_check` to `true` you can enforce only create a runner if the event has a correlated queued job. Setting this can avoid creating useless runners, for example whn jobs got cancelled before a runner is created. We suggest to use this in combination with a pool. -- To ensure runners are created in the same order GitHub sends the events we use by default a FIFO queue, this is mainly relevant for repo level runners. For ephemeral runners you can set `fifo_build_queue` to `false`. -- Error related to scaling should be retried via SQS. You can configure `job_queue_retention_in_seconds` `redrive_build_queue` to tune the behavior. We have no mechanism to avoid events will never processed, which means potential no runner could be created and the job in GitHub can time out in 6 hours. +## License -The example for [ephemeral runners](./examples/ephemeral) is based on the [default example](./examples/default). Have look on the diff to see the major configuration differences. +This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details. -### Prebuilt Images +## Contributing -This module also allows you to run agents from a prebuilt AMI to gain faster startup times. You can find more information in [the image README.md](/images/README.md) +We welcome contributions, please check out the [contribution guide](CONTRIBUTING.md). Be aware we use [pre commit hooks](https://pre-commit.com/) to update the docs. -### Experimental - Optional queue to publish GitHub workflow job events - -This queue is an experimental feature to allow you to receive a copy of the wokflow_jobs events sent by the GItHub App. For example to calculate matrix or monitor the system. +## Philips Forest -To enable the feature set `enable_workflow_job_events_queue = true`. Be-aware the feature in experimental! +This module is part of the Philips Forest. -Messages received on the queue are using the same format as published by GitHub wrapped in a property `workflowJobEvent`. +```plain + ___ _ + / __\__ _ __ ___ ___| |_ + / _\/ _ \| '__/ _ \/ __| __| + / / | (_) | | | __/\__ \ |_ + \/ \___/|_| \___||___/\__| + Infrastructure ``` -export interface GithubWorkflowEvent { - workflowJobEvent: WorkflowJobEvent; -} -``` -This extendible format allows to add more fields to be added if needed. -You can configure the queue by setting properties to `workflow_job_events_queue_config` - -NOTE: By default, a runner AMI update requires a re-apply of this terraform config (the runner AMI ID is looked up by a terraform data source). To avoid this, you can use `ami_id_ssm_parameter_name` to have the scale-up lambda dynamically lookup the runner AMI ID from an SSM parameter at instance launch time. Said SSM parameter is managed outside of this module (e.g. by a runner AMI build workflow). -## Examples +Talk to the forestkeepers in the `runners-channel` on Slack. -Examples are located in the [examples](./examples) directory. The following examples are provided: - -- _[Default](examples/default/README.md)_: The default example of the module -- _[ARM64](examples/arm64/README.md)_: Example usage with ARM64 architecture -- _[Ubuntu](examples/ubuntu/README.md)_: Example usage of creating a runner using Ubuntu AMIs. -- _[Windows](examples/windows/README.md)_: Example usage of creating a runner using Windows as the OS. -- _[Ephemeral](examples/ephemeral/README.md)_: Example usages of ephemeral runners based on the default example. -- _[Prebuilt Images](examples/prebuilt/README.md)_: Example usages of deploying runners with a custom prebuilt image. -- _[Permissions boundary](examples/permissions-boundary/README.md)_: Example usages of permissions boundaries. - -## Sub modules - -The module contains several submodules, you can use the module via the main module or assemble your own setup by initializing the submodules yourself. - -The following submodules are the core of the module and are mandatory: - -- _[runner-binaries-syncer](./modules/runner-binaries-syncer/README.md)_ - Syncs the action runner distribution. -- _[runners](./modules/runners/README.md)_ - Scales the action runners up and down -- _[webhook](./modules/webhook/README.md)_ - Handles GitHub webhooks - -The following sub modules are optional and are provided as example or utility: - -- _[download-lambda](./modules/download-lambda/README.md)_ - Utility module to download lambda artifacts from GitHub Release -- _[setup-iam-permissions](./modules/setup-iam-permissions/README.md)_ - Example module to setup permission boundaries - -### ARM64 configuration for submodules - -When using the top level module configure `runner_architecture = "arm64"` and ensure the list of `instance_types` matches. When not using the top-level, ensure these properties are set on the submodules. - -## Debugging - -In case the setup does not work as intended follow the trace of events: - -- In the GitHub App configuration, the Advanced page displays all webhook events that were sent. -- In AWS CloudWatch, every lambda has a log group. Look at the logs of the `webhook` and `scale-up` lambdas. -- In AWS SQS you can see messages available or in flight. -- Once an EC2 instance is running, you can connect to it in the EC2 user interface using Session Manager (use `enable_ssm_on_runners = true`). Check the user data script using `cat /var/log/user-data.log`. By default several log files of the instances are streamed to AWS CloudWatch, look for a log group named `/runners`. In the log group you should see at least the log streams for the user data installation and runner agent. -- Registered instances should show up in the Settings - Actions page of the repository or organization (depending on the installation mode). - -## Security Consideration - -This module creates resources in your AWS infrastructure, and EC2 instances for hosting the self-hosted runners on-demand. IAM permissions are set to a minimal level, and could be further limit by using permission boundaries. Instances permissions are limit to retrieve and delete the registration token, access the instance own tags, and terminate the instance itself. +[![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge&logo=slack&logoColor=white)](https://join.slack.com/t/philips-software/shared_invite/zt-xecw65v5-i1531hGP~mdVwgxLFx7ckg) -The examples are using standard AMI's for different operation systems. Instances are not hardened, and sudo operation are not blocked. To provide an out of the box working expierence by default the module installs and configure the runner. However secrets are not hard coded, they finally end up in the memory of the instances. You can harden the instance by providing your own AMI and overwriting the cloud-init script. -We welcome any improvement to the standard module to make the default as secure as possible, in the end it remains your responsibility to keep your environment secure. +
+Terraform root module documention + - + ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.14.1 | -| [aws](#requirement\_aws) | ~> 4.15 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [random](#requirement\_random) | ~> 3.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | ~> 4.15 | -| [random](#provider\_random) | n/a | +| [aws](#provider\_aws) | 5.31.0 | +| [random](#provider\_random) | 3.6.0 | ## Modules | Name | Source | Version | |------|--------|---------| +| [ami\_housekeeper](#module\_ami\_housekeeper) | ./modules/ami-housekeeper | n/a | +| [instance\_termination\_watcher](#module\_instance\_termination\_watcher) | ./modules/termination-watcher | n/a | | [runner\_binaries](#module\_runner\_binaries) | ./modules/runner-binaries-syncer | n/a | | [runners](#module\_runners) | ./modules/runners | n/a | | [ssm](#module\_ssm) | ./modules/ssm | n/a | @@ -414,8 +110,10 @@ We welcome any improvement to the standard module to make the default as secure |------|------| | [aws_sqs_queue.queued_builds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | | [aws_sqs_queue.queued_builds_dlq](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.webhook_events_workflow_job_queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | | [aws_sqs_queue_policy.build_queue_dlq_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [aws_sqs_queue_policy.build_queue_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | +| [aws_sqs_queue_policy.webhook_events_workflow_job_queue_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | | [random_string.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | | [aws_iam_policy_document.deny_unsecure_transport](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -423,135 +121,145 @@ We welcome any improvement to the standard module to make the default as secure | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami\_filter](#input\_ami\_filter) | List of maps used to create the AMI filter for the action runner AMI. By default amazon linux 2 is used. | `map(list(string))` | `null` | no | +| [ami\_filter](#input\_ami\_filter) | Map of lists used to create the AMI filter for the action runner AMI. | `map(list(string))` |
{
"state": [
"available"
]
}
| no | +| [ami\_housekeeper\_cleanup\_config](#input\_ami\_housekeeper\_cleanup\_config) | Configuration for AMI cleanup.

`amiFilters` - Filters to use when searching for AMIs to cleanup. Default filter for images owned by the account and that are available.
`dryRun` - If true, no AMIs will be deregistered. Default false.
`launchTemplateNames` - Launch template names to use when searching for AMIs to cleanup. Default no launch templates.
`maxItems` - The maximum numer of AMI's tha will be queried for cleanup. Default no maximum.
`minimumDaysOld` - Minimum number of days old an AMI must be to be considered for cleanup. Default 30.
`ssmParameterNames` - SSM parameter names to use when searching for AMIs to cleanup. This parameter should be set when using SSM to configure the AMI to use. Default no SSM parameters. |
object({
amiFilters = optional(list(object({
Name = string
Values = list(string)
})),
[{
Name : "state",
Values : ["available"],
},
{
Name : "image-type",
Values : ["machine"],
}]
)
dryRun = optional(bool, false)
launchTemplateNames = optional(list(string))
maxItems = optional(number)
minimumDaysOld = optional(number, 30)
ssmParameterNames = optional(list(string))
})
| `{}` | no | +| [ami\_housekeeper\_lambda\_s3\_key](#input\_ami\_housekeeper\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [ami\_housekeeper\_lambda\_s3\_object\_version](#input\_ami\_housekeeper\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [ami\_housekeeper\_lambda\_schedule\_expression](#input\_ami\_housekeeper\_lambda\_schedule\_expression) | Scheduler expression for action runner binary syncer. | `string` | `"rate(1 day)"` | no | +| [ami\_housekeeper\_lambda\_timeout](#input\_ami\_housekeeper\_lambda\_timeout) | Time out of the lambda in seconds. | `number` | `300` | no | +| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | +| [ami\_id\_ssm\_parameter\_name](#input\_ami\_id\_ssm\_parameter\_name) | Externally managed SSM parameter (of data type aws:ec2:image) that contains the AMI ID to launch runner instances from. Overrides ami\_filter | `string` | `null` | no | +| [ami\_kms\_key\_arn](#input\_ami\_kms\_key\_arn) | Optional CMK Key ARN to be used to launch an instance from a shared encrypted AMI | `string` | `null` | no | | [ami\_owners](#input\_ami\_owners) | The list of owners used to select the AMI of action runner instances. | `list(string)` |
[
"amazon"
]
| no | -| [ami\_id\_ssm\_parameter\_name](#input\_ami\_id\_ssm\_parameter\_name) | Optional SSM parameter that contains the runner AMI ID to launch instances from. Overrides `ami_filter`. The parameter value is managed outside of this module (e.g. in a runner AMI build workflow). This allows for AMI updates without having to re-apply this terraform config. | `string` | `null` | no | +| [associate\_public\_ipv4\_address](#input\_associate\_public\_ipv4\_address) | Associate public IPv4 with the runner. Only tested with IPv4 | `bool` | `false` | no | | [aws\_partition](#input\_aws\_partition) | (optiona) partition in the arn namespace to use if not 'aws' | `string` | `"aws"` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes | -| [block\_device\_mappings](#input\_block\_device\_mappings) | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`, `snapshot_id`. |
list(object({
delete_on_termination = bool
device_name = string
encrypted = bool
iops = number
kms_key_id = string
snapshot_id = string
throughput = number
volume_size = number
volume_type = string
}))
|
[
{
"delete_on_termination": true,
"device_name": "/dev/xvda",
"encrypted": true,
"iops": null,
"kms_key_id": null,
"snapshot_id": null,
"throughput": null,
"volume_size": 30,
"volume_type": "gp3"
}
]
| no | -| [cloudwatch\_config](#input\_cloudwatch\_config) | (optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details. | `string` | `null` | no | -| [create\_service\_linked\_role\_spot](#input\_create\_service\_linked\_role\_spot) | (optional) create the serviced linked role for spot instances that is required by the scale-up lambda. | `bool` | `false` | no | +| [block\_device\_mappings](#input\_block\_device\_mappings) | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`, `snapshot_id`. |
list(object({
delete_on_termination = optional(bool, true)
device_name = optional(string, "/dev/xvda")
encrypted = optional(bool, true)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_size = number
volume_type = optional(string, "gp3")
}))
|
[
{
"volume_size": 30
}
]
| no | +| [cloudwatch\_config](#input\_cloudwatch\_config) | (optional) Replaces the module's default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details. | `string` | `null` | no | +| [create\_service\_linked\_role\_spot](#input\_create\_service\_linked\_role\_spot) | (optional) create the service linked role for spot instances that is required by the scale-up lambda. | `bool` | `false` | no | | [delay\_webhook\_event](#input\_delay\_webhook\_event) | The number of seconds the event accepted by the webhook is invisible on the queue before the scale up lambda will receive the event. | `number` | `30` | no | -| [disable\_runner\_autoupdate](#input\_disable\_runner\_autoupdate) | Disable the auto update of the github runner agent. Be-aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/) | `bool` | `false` | no | -| [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no | +| [disable\_runner\_autoupdate](#input\_disable\_runner\_autoupdate) | Disable the auto update of the github runner agent. Be aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/) | `bool` | `false` | no | +| [enable\_ami\_housekeeper](#input\_enable\_ami\_housekeeper) | Option to disable the lambda to clean up old AMIs. | `bool` | `false` | no | +| [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Enables the cloudwatch agent on the ec2 runner instances. The runner uses a default config that can be overridden via `cloudwatch_config`. | `bool` | `true` | no | | [enable\_ephemeral\_runners](#input\_enable\_ephemeral\_runners) | Enable ephemeral runners, runners will only be used once. | `bool` | `false` | no | -| [enable\_job\_queued\_check](#input\_enable\_job\_queued\_check) | Only scale if the job event received by the scale up lambda is is in the state queued. By default enabled for non ephemeral runners and disabled for ephemeral. Set this variable to overwrite the default behavior. | `bool` | `null` | no | -| [enable\_managed\_runner\_security\_group](#input\_enable\_managed\_runner\_security\_group) | Enabling the default managed security group creation. Unmanaged security groups can be specified via `runner_additional_security_group_ids`. | `bool` | `true` | no | +| [enable\_event\_rule\_binaries\_syncer](#input\_enable\_event\_rule\_binaries\_syncer) | DEPRECATED: Replaced by `state_event_rule_binaries_syncer`. | `bool` | `null` | no | +| [enable\_fifo\_build\_queue](#input\_enable\_fifo\_build\_queue) | Enable a FIFO queue to keep the order of events received by the webhook. Recommended for repo level runners. | `bool` | `false` | no | +| [enable\_jit\_config](#input\_enable\_jit\_config) | Overwrite the default behavior for JIT configuration. By default JIT configuration is enabled for ephemeral runners and disabled for non-ephemeral runners. In case of GHES check first if the JIT config API is avaialbe. In case you upgradeing from 3.x to 4.x you can set `enable_jit_config` to `false` to avoid a breaking change when having your own AMI. | `bool` | `null` | no | +| [enable\_job\_queued\_check](#input\_enable\_job\_queued\_check) | Only scale if the job event received by the scale up lambda is in the queued state. By default enabled for non ephemeral runners and disabled for ephemeral. Set this variable to overwrite the default behavior. | `bool` | `null` | no | +| [enable\_managed\_runner\_security\_group](#input\_enable\_managed\_runner\_security\_group) | Enables creation of the default managed security group. Unmanaged security groups can be specified via `runner_additional_security_group_ids`. | `bool` | `true` | no | | [enable\_organization\_runners](#input\_enable\_organization\_runners) | Register runners to organization, instead of repo level | `bool` | `false` | no | | [enable\_runner\_binaries\_syncer](#input\_enable\_runner\_binaries\_syncer) | Option to disable the lambda to sync GitHub runner distribution, useful when using a pre-build AMI. | `bool` | `true` | no | | [enable\_runner\_detailed\_monitoring](#input\_enable\_runner\_detailed\_monitoring) | Should detailed monitoring be enabled for the runner. Set this to true if you want to use detailed monitoring. See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html for details. | `bool` | `false` | no | -| [enable\_ssm\_on\_runners](#input\_enable\_ssm\_on\_runners) | Enable to allow access the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | `false` | no | +| [enable\_runner\_on\_demand\_failover\_for\_errors](#input\_enable\_runner\_on\_demand\_failover\_for\_errors) | Enable on-demand failover. For example to fall back to on demand when no spot capacity is available the variable can be set to `InsufficientInstanceCapacity`. When not defined the default behavior is to retry later. | `list(string)` | `[]` | no | +| [enable\_runner\_workflow\_job\_labels\_check\_all](#input\_enable\_runner\_workflow\_job\_labels\_check\_all) | If set to true all labels in the workflow job must match the GitHub labels (os, architecture and `self-hosted`). When false if __any__ label matches it will trigger the webhook. | `bool` | `true` | no | +| [enable\_ssm\_on\_runners](#input\_enable\_ssm\_on\_runners) | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | `false` | no | | [enable\_user\_data\_debug\_logging\_runner](#input\_enable\_user\_data\_debug\_logging\_runner) | Option to enable debug logging for user-data, this logs all secrets as well. | `bool` | `false` | no | -| [enabled\_userdata](#input\_enabled\_userdata) | Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI. | `bool` | `true` | no | -| [environment](#input\_environment) | DEPRECATED, no longer used. See `prefix` | `string` | `null` | no | -| [fifo\_build\_queue](#input\_fifo\_build\_queue) | Enable a FIFO queue to remain the order of events received by the webhook. Suggest to set to true for repo level runners. | `bool` | `false` | no | +| [enable\_userdata](#input\_enable\_userdata) | Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI. | `bool` | `true` | no | +| [enable\_workflow\_job\_events\_queue](#input\_enable\_workflow\_job\_events\_queue) | Enabling this experimental feature will create a secondory sqs queue to which a copy of the workflow\_job event will be delivered. | `bool` | `false` | no | | [ghes\_ssl\_verify](#input\_ghes\_ssl\_verify) | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | | [ghes\_url](#input\_ghes\_url) | GitHub Enterprise Server URL. Example: https://github.internal.co - DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
webhook_secret = string
})
| n/a | yes | -| [idle\_config](#input\_idle\_config) | List of time period that can be defined as cron expression to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle. |
list(object({
cron = string
timeZone = string
idleCount = number
}))
| `[]` | no | -| [instance\_allocation\_strategy](#input\_instance\_allocation\_strategy) | The allocation strategy for spot instances. AWS recommends to use `price-capacity-optimized` however the AWS default is `lowest-price`. | `string` | `"lowest-price"` | no | -| [instance\_max\_spot\_price](#input\_instance\_max\_spot\_price) | Max price price for spot intances per hour. This variable will be passed to the create fleet as max spot price for the fleet. | `string` | `null` | no | +| [idle\_config](#input\_idle\_config) | List of time periods, defined as a cron expression, to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle. |
list(object({
cron = string
timeZone = string
idleCount = number
evictionStrategy = optional(string, "oldest_first")
}))
| `[]` | no | +| [instance\_allocation\_strategy](#input\_instance\_allocation\_strategy) | The allocation strategy for spot instances. AWS recommends using `price-capacity-optimized` however the AWS default is `lowest-price`. | `string` | `"lowest-price"` | no | +| [instance\_max\_spot\_price](#input\_instance\_max\_spot\_price) | Max price price for spot instances per hour. This variable will be passed to the create fleet as max spot price for the fleet. | `string` | `null` | no | | [instance\_profile\_path](#input\_instance\_profile\_path) | The path that will be added to the instance\_profile, if not set the environment name will be used. | `string` | `null` | no | | [instance\_target\_capacity\_type](#input\_instance\_target\_capacity\_type) | Default lifecycle used for runner instances, can be either `spot` or `on-demand`. | `string` | `"spot"` | no | -| [instance\_type](#input\_instance\_type) | [DEPRECATED] See instance\_types. | `string` | `null` | no | -| [instance\_types](#input\_instance\_types) | List of instance types for the action runner. Defaults are based on runner\_os (amzn2 for linux and Windows Server Core for win). | `list(string)` |
[
"m5.large",
"c5.large"
]
| no | -| [job\_queue\_retention\_in\_seconds](#input\_job\_queue\_retention\_in\_seconds) | The number of seconds the job is held in the queue before it is purged | `number` | `86400` | no | +| [instance\_termination\_watcher](#input\_instance\_termination\_watcher) | Configuration for the instance termination watcher. This feature is Beta, changes will not trigger a major release as long in beta.

`enable`: Enable or disable the spot termination watcher.
`enable_metrics`: Enable or disable the metrics for the spot termination watcher.
`memory_size`: Memory size linit in MB of the lambda.
`s3_key`: S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas.
`s3_object_version`: S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket.
`timeout`: Time out of the lambda in seconds.
`zip`: File location of the lambda zip file. |
object({
enable = optional(bool, false)
enable_metric = optional(object({
spot_warning = optional(bool, false)
}))
memory_size = optional(number, null)
s3_key = optional(string, null)
s3_object_version = optional(string, null)
timeout = optional(number, null)
zip = optional(string, null)
})
| `{}` | no | +| [instance\_types](#input\_instance\_types) | List of instance types for the action runner. Defaults are based on runner\_os (al2023 for linux and Windows Server Core for win). | `list(string)` |
[
"m5.large",
"c5.large"
]
| no | +| [job\_queue\_retention\_in\_seconds](#input\_job\_queue\_retention\_in\_seconds) | The number of seconds the job is held in the queue before it is purged. | `number` | `86400` | no | | [key\_name](#input\_key\_name) | Key pair name | `string` | `null` | no | | [kms\_key\_arn](#input\_kms\_key\_arn) | Optional CMK Key ARN to be used for Parameter Store. This key must be in the current account. | `string` | `null` | no | -| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"x86_64"` | no | +| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"arm64"` | no | | [lambda\_principals](#input\_lambda\_principals) | (Optional) add extra principals to the role created for execution of the lambda, e.g. for local testing. |
list(object({
type = string
identifiers = list(string)
}))
| `[]` | no | -| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs16.x"` | no | -| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | +| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs20.x"` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `string` | `null` | no | | [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | | [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_tags](#input\_lambda\_tags) | Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags. | `map(string)` | `{}` | no | +| [lambda\_tracing\_mode](#input\_lambda\_tracing\_mode) | DEPRECATED: Replaced by `tracing_config`. | `string` | `null` | no | | [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | -| [log\_type](#input\_log\_type) | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | -| [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with | `string` | `null` | no | +| [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with. | `string` | `null` | no | | [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | -| [market\_options](#input\_market\_options) | DEPCRECATED: Replaced by `instance_target_capacity_type`. | `string` | `null` | no | -| [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated if not busy. | `number` | `null` | no | -| [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for week days to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. |
list(object({
schedule_expression = string
size = number
}))
| `[]` | no | +| [matcher\_config\_parameter\_store\_tier](#input\_matcher\_config\_parameter\_store\_tier) | The tier of the parameter store for the matcher configuration. Valid values are `Standard`, and `Advanced`. | `string` | `"Standard"` | no | +| [metrics\_namespace](#input\_metrics\_namespace) | The namespace for the metrics created by the module. Merics will only be created if explicit enabled. | `string` | `"GitHub Runners"` | no | +| [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated, if not busy. | `number` | `null` | no | +| [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for weekdays to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. |
list(object({
schedule_expression = string
size = number
}))
| `[]` | no | +| [pool\_lambda\_memory\_size](#input\_pool\_lambda\_memory\_size) | Memory size limit for scale-up lambda. | `number` | `512` | no | | [pool\_lambda\_reserved\_concurrent\_executions](#input\_pool\_lambda\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no | | [pool\_lambda\_timeout](#input\_pool\_lambda\_timeout) | Time out for the pool lambda in seconds. | `number` | `60` | no | | [pool\_runner\_owner](#input\_pool\_runner\_owner) | The pool will deploy runners to the GitHub org ID, set this value to the org to which you want the runners deployed. Repo level is not supported. | `string` | `null` | no | | [prefix](#input\_prefix) | The prefix used for naming resources | `string` | `"github-actions"` | no | | [queue\_encryption](#input\_queue\_encryption) | Configure how data on queues managed by the modules in ecrypted at REST. Options are encryped via SSE, non encrypted and via KMSS. By default encryptes via SSE is enabled. See for more details the Terraform `aws_sqs_queue` resource https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue. |
object({
kms_data_key_reuse_period_seconds = number
kms_master_key_id = string
sqs_managed_sse_enabled = bool
})
|
{
"kms_data_key_reuse_period_seconds": null,
"kms_master_key_id": null,
"sqs_managed_sse_enabled": true
}
| no | | [redrive\_build\_queue](#input\_redrive\_build\_queue) | Set options to attach (optional) a dead letter queue to the build queue, the queue between the webhook and the scale up lambda. You have the following options. 1. Disable by setting `enabled` to false. 2. Enable by setting `enabled` to `true`, `maxReceiveCount` to a number of max retries. |
object({
enabled = bool
maxReceiveCount = number
})
|
{
"enabled": false,
"maxReceiveCount": null
}
| no | -| [repository\_white\_list](#input\_repository\_white\_list) | List of repositories allowed to use the github app | `list(string)` | `[]` | no | +| [repository\_white\_list](#input\_repository\_white\_list) | List of github repository full names (owner/repo\_name) that will be allowed to use the github app. Leave empty for no filtering. | `list(string)` | `[]` | no | | [role\_path](#input\_role\_path) | The path that will be added to role path for created roles, if not set the environment name will be used. | `string` | `null` | no | | [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | Permissions boundary that will be added to the created roles. | `string` | `null` | no | -| [runner\_additional\_security\_group\_ids](#input\_runner\_additional\_security\_group\_ids) | (optional) List of additional security groups IDs to apply to the runner | `list(string)` | `[]` | no | -| [runner\_allow\_prerelease\_binaries](#input\_runner\_allow\_prerelease\_binaries) | (Deprecated, no longer used), allow the runners to update to prerelease binaries. | `bool` | `null` | no | +| [runner\_additional\_security\_group\_ids](#input\_runner\_additional\_security\_group\_ids) | (optional) List of additional security groups IDs to apply to the runner. | `list(string)` | `[]` | no | | [runner\_architecture](#input\_runner\_architecture) | The platform architecture of the runner instance\_type. | `string` | `"x64"` | no | | [runner\_as\_root](#input\_runner\_as\_root) | Run the action runner under the root user. Variable `runner_run_as` will be ignored. | `bool` | `false` | no | | [runner\_binaries\_s3\_logging\_bucket](#input\_runner\_binaries\_s3\_logging\_bucket) | Bucket for action runner distribution bucket access logging. | `string` | `null` | no | | [runner\_binaries\_s3\_logging\_bucket\_prefix](#input\_runner\_binaries\_s3\_logging\_bucket\_prefix) | Bucket prefix for action runner distribution bucket access logging. | `string` | `null` | no | -| [runner\_binaries\_s3\_sse\_configuration](#input\_runner\_binaries\_s3\_sse\_configuration) | Map containing server-side encryption configuration for runner-binaries S3 bucket. | `any` | `{}` | no | +| [runner\_binaries\_s3\_sse\_configuration](#input\_runner\_binaries\_s3\_sse\_configuration) | Map containing server-side encryption configuration for runner-binaries S3 bucket. | `any` |
{
"rule": {
"apply_server_side_encryption_by_default": {
"sse_algorithm": "AES256"
}
}
}
| no | +| [runner\_binaries\_s3\_versioning](#input\_runner\_binaries\_s3\_versioning) | Status of S3 versioning for runner-binaries S3 bucket. Once set to Enabled the change cannot be reverted via Terraform! | `string` | `"Disabled"` | no | +| [runner\_binaries\_syncer\_lambda\_memory\_size](#input\_runner\_binaries\_syncer\_lambda\_memory\_size) | Memory size limit in MB for binary syncer lambda. | `number` | `256` | no | | [runner\_binaries\_syncer\_lambda\_timeout](#input\_runner\_binaries\_syncer\_lambda\_timeout) | Time out of the binaries sync lambda in seconds. | `number` | `300` | no | | [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | File location of the binaries sync lambda zip file. | `string` | `null` | no | | [runner\_boot\_time\_in\_minutes](#input\_runner\_boot\_time\_in\_minutes) | The minimum time for an EC2 runner to boot and register as a runner. | `number` | `5` | no | +| [runner\_credit\_specification](#input\_runner\_credit\_specification) | The credit option for CPU usage of a T instance. Can be unset, "standard" or "unlimited". | `string` | `null` | no | | [runner\_ec2\_tags](#input\_runner\_ec2\_tags) | Map of tags that will be added to the launch template instance tag specifications. | `map(string)` | `{}` | no | | [runner\_egress\_rules](#input\_runner\_egress\_rules) | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | -| [runner\_enable\_workflow\_job\_labels\_check](#input\_runner\_enable\_workflow\_job\_labels\_check) | If set to true all labels in the workflow job even are matched against the custom labels and GitHub labels (os, architecture and `self-hosted`). When the labels are not matching the event is dropped at the webhook. | `bool` | `false` | no | -| [runner\_enable\_workflow\_job\_labels\_check\_all](#input\_runner\_enable\_workflow\_job\_labels\_check\_all) | If set to true all labels in the workflow job must match the GitHub labels (os, architecture and `self-hosted`). When false if __any__ label matches it will trigger the webhook. `runner_enable_workflow_job_labels_check` must be true for this to take effect. | `bool` | `true` | no | -| [runner\_extra\_labels](#input\_runner\_extra\_labels) | Extra (custom) labels for the runners (GitHub). Separate each label by a comma. Labels checks on the webhook can be enforced by setting `enable_workflow_job_labels_check`. GitHub read-only labels should not be provided. | `string` | `""` | no | +| [runner\_extra\_labels](#input\_runner\_extra\_labels) | Extra (custom) labels for the runners (GitHub). Labels checks on the webhook can be enforced by setting `enable_runner_workflow_job_labels_check_all`. GitHub read-only labels should not be provided. | `list(string)` | `[]` | no | | [runner\_group\_name](#input\_runner\_group\_name) | Name of the runner group. | `string` | `"Default"` | no | | [runner\_iam\_role\_managed\_policy\_arns](#input\_runner\_iam\_role\_managed\_policy\_arns) | Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role | `list(string)` | `[]` | no | | [runner\_log\_files](#input\_runner\_log\_files) | (optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details. |
list(object({
log_group_name = string
prefix_log_group = bool
file_path = string
log_stream_name = string
}))
| `null` | no | -| [runner\_metadata\_options](#input\_runner\_metadata\_options) | Metadata options for the ec2 runner instances. | `map(any)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "optional"
}
| no | +| [runner\_metadata\_options](#input\_runner\_metadata\_options) | Metadata options for the ec2 runner instances. By default, the module uses metadata tags for bootstrapping the runner, only disable `instance_metadata_tags` when using custom scripts for starting the runner. | `map(any)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required",
"instance_metadata_tags": "enabled"
}
| no | +| [runner\_name\_prefix](#input\_runner\_name\_prefix) | The prefix used for the GitHub runner name. The prefix will be used in the default start script to prefix the instance name when register the runner in GitHub. The value is availabe via an EC2 tag 'ghr:runner\_name\_prefix'. | `string` | `""` | no | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux,windows). | `string` | `"linux"` | no | | [runner\_run\_as](#input\_runner\_run\_as) | Run the GitHub actions agent as user. | `string` | `"ec2-user"` | no | -| [runners\_lambda\_s3\_key](#input\_runners\_lambda\_s3\_key) | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| [runners\_lambda\_s3\_object\_version](#input\_runners\_lambda\_s3\_object\_version) | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | +| [runners\_ebs\_optimized](#input\_runners\_ebs\_optimized) | Enable EBS optimization for the runner instances. | `bool` | `false` | no | +| [runners\_lambda\_s3\_key](#input\_runners\_lambda\_s3\_key) | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [runners\_lambda\_s3\_object\_version](#input\_runners\_lambda\_s3\_object\_version) | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | | [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | File location of the lambda zip file for scaling runners. | `string` | `null` | no | | [runners\_maximum\_count](#input\_runners\_maximum\_count) | The maximum number of runners that will be created. | `number` | `3` | no | +| [runners\_scale\_down\_lambda\_memory\_size](#input\_runners\_scale\_down\_lambda\_memory\_size) | Memory size limit in MB for scale-down lambda. | `number` | `512` | no | | [runners\_scale\_down\_lambda\_timeout](#input\_runners\_scale\_down\_lambda\_timeout) | Time out for the scale down lambda in seconds. | `number` | `60` | no | +| [runners\_scale\_up\_Lambda\_memory\_size](#input\_runners\_scale\_up\_Lambda\_memory\_size) | Memory size limit in MB for scale-up lambda. | `number` | `null` | no | +| [runners\_scale\_up\_lambda\_memory\_size](#input\_runners\_scale\_up\_lambda\_memory\_size) | Memory size limit in MB for scale-up lambda. | `number` | `512` | no | | [runners\_scale\_up\_lambda\_timeout](#input\_runners\_scale\_up\_lambda\_timeout) | Time out for the scale up lambda in seconds. | `number` | `30` | no | +| [runners\_ssm\_housekeeper](#input\_runners\_ssm\_housekeeper) | Configuration for the SSM housekeeper lambda. This lambda deletes token / JIT config from SSM.

`schedule_expression`: is used to configure the schedule for the lambda.
`enabled`: enable or disable the lambda trigger via the EventBridge.
`lambda_memory_size`: lambda memery size limit.
`lambda_timeout`: timeout for the lambda in seconds.
`config`: configuration for the lambda function. Token path will be read by default from the module. |
object({
schedule_expression = optional(string, "rate(1 day)")
enabled = optional(bool, true)
lambda_memory_size = optional(number, 512)
lambda_timeout = optional(number, 60)
config = object({
tokenPath = optional(string)
minimumDaysOld = optional(number, 1)
dryRun = optional(bool, false)
})
})
|
{
"config": {}
}
| no | | [scale\_down\_schedule\_expression](#input\_scale\_down\_schedule\_expression) | Scheduler expression to check every x for scale down. | `string` | `"cron(*/5 * * * ? *)"` | no | | [scale\_up\_reserved\_concurrent\_executions](#input\_scale\_up\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no | -| [subnet\_ids](#input\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | n/a | yes | -| [syncer\_lambda\_s3\_key](#input\_syncer\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| [syncer\_lambda\_s3\_object\_version](#input\_syncer\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | +| [ssm\_paths](#input\_ssm\_paths) | The root path used in SSM to store configuration and secrets. |
object({
root = optional(string, "github-action-runners")
app = optional(string, "app")
runners = optional(string, "runners")
webhook = optional(string, "webhook")
use_prefix = optional(bool, true)
})
| `{}` | no | +| [state\_event\_rule\_binaries\_syncer](#input\_state\_event\_rule\_binaries\_syncer) | Option to disable EventBridge Lambda trigger for the binary syncer, useful to stop automatic updates of binary distribution | `string` | `"ENABLED"` | no | +| [subnet\_ids](#input\_subnet\_ids) | List of subnets in which the action runner instances will be launched. The subnets need to exist in the configured VPC (`vpc_id`), and must reside in different availability zones (see https://github.com/philips-labs/terraform-aws-github-runner/issues/2904) | `list(string)` | n/a | yes | +| [syncer\_lambda\_s3\_key](#input\_syncer\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using an S3 bucket to specify lambdas. | `string` | `null` | no | +| [syncer\_lambda\_s3\_object\_version](#input\_syncer\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | | [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | +| [userdata\_content](#input\_userdata\_content) | Alternative user-data content, replacing the templated one. By providing your own user\_data you have to take care of installing all required software, including the action runner and registering the runner. Be-aware configuration paramaters in SSM as well as tags are treated as internals. Changes will not trigger a breaking release. | `string` | `null` | no | | [userdata\_post\_install](#input\_userdata\_post\_install) | Script to be ran after the GitHub Actions runner is installed on the EC2 instances | `string` | `""` | no | | [userdata\_pre\_install](#input\_userdata\_pre\_install) | Script to be ran before the GitHub Actions runner is installed on the EC2 instances | `string` | `""` | no | -| [userdata\_template](#input\_userdata\_template) | Alternative user-data template, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no | +| [userdata\_template](#input\_userdata\_template) | Alternative user-data template file path, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no | | [vpc\_id](#input\_vpc\_id) | The VPC for security groups of the action runners. | `string` | n/a | yes | -| [webhook\_lambda\_apigateway\_access\_log\_settings](#input\_webhook\_lambda\_apigateway\_access\_log\_settings) | n/a |
object({
destination_arn = string
format = string
})
| `null` | no | -| [webhook\_lambda\_s3\_key](#input\_webhook\_lambda\_s3\_key) | S3 key for webhook lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| [webhook\_lambda\_s3\_object\_version](#input\_webhook\_lambda\_s3\_object\_version) | S3 object version for webhook lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | +| [webhook\_lambda\_apigateway\_access\_log\_settings](#input\_webhook\_lambda\_apigateway\_access\_log\_settings) | Access log settings for webhook API gateway. |
object({
destination_arn = string
format = string
})
| `null` | no | +| [webhook\_lambda\_memory\_size](#input\_webhook\_lambda\_memory\_size) | Memory size limit in MB for webhook lambda in. | `number` | `256` | no | +| [webhook\_lambda\_s3\_key](#input\_webhook\_lambda\_s3\_key) | S3 key for webhook lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [webhook\_lambda\_s3\_object\_version](#input\_webhook\_lambda\_s3\_object\_version) | S3 object version for webhook lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | | [webhook\_lambda\_timeout](#input\_webhook\_lambda\_timeout) | Time out of the webhook lambda in seconds. | `number` | `10` | no | | [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | File location of the webhook lambda zip file. | `string` | `null` | no | +| [workflow\_job\_queue\_configuration](#input\_workflow\_job\_queue\_configuration) | Configuration options for workflow job queue which is only applicable if the flag enable\_workflow\_job\_events\_queue is set to true. |
object({
delay_seconds = number
visibility_timeout_seconds = number
message_retention_seconds = number
})
|
{
"delay_seconds": null,
"message_retention_seconds": null,
"visibility_timeout_seconds": null
}
| no | ## Outputs | Name | Description | |------|-------------| | [binaries\_syncer](#output\_binaries\_syncer) | n/a | +| [instance\_termination\_watcher](#output\_instance\_termination\_watcher) | n/a | | [queues](#output\_queues) | SQS queues. | | [runners](#output\_runners) | n/a | | [ssm\_parameters](#output\_ssm\_parameters) | n/a | | [webhook](#output\_webhook) | n/a | - - -## Contribution - -We welcome contribution, please checkout the [contribution guide](CONTRIBUTING.md). Be-aware we use [pre commit hooks](https://pre-commit.com/) to update the docs. + + -## Philips Forest - -This module is part of the Philips Forest. - -```plain - ___ _ - / __\__ _ __ ___ ___| |_ - / _\/ _ \| '__/ _ \/ __| __| - / / | (_) | | | __/\__ \ |_ - \/ \___/|_| \___||___/\__| - - Infrastructure -``` - -Talk to the forestkeepers in the `runners`-channel on Slack. - -[![Slack](https://img.shields.io/badge/Slack-4A154B?style=for-the-badge&logo=slack&logoColor=white)](https://join.slack.com/t/philips-software/shared_invite/zt-xecw65v5-i1531hGP~mdVwgxLFx7ckg) +
diff --git a/docs/additional_notes.md b/docs/additional_notes.md new file mode 100644 index 0000000000..8d8d3aa100 --- /dev/null +++ b/docs/additional_notes.md @@ -0,0 +1,34 @@ + +# Runner Labels + +Some CI systems require that all labels match between a job and a runner. In the case of GitHub Actions, workflows will be assigned to runners which have all the labels requested by the workflow, however it is not necessary the workflow mentions all labels. + +Labels specify the capabilities the runners have. The labels in the workflow are the capabilities needed. If the capabilities requested by the workflow are provided by the runners, there is match. + +Examples: + +| Runner Labels | Workflow runs-on: | Result | +| ------------- | ------------- | ------------- | +| 'self-hosted', 'Linux', 'X64' | self-hosted | matches | +| 'self-hosted', 'Linux', 'X64' | Linux | matches | +| 'self-hosted', 'Linux', 'X64' | X64 | matches | +| 'self-hosted', 'Linux', 'X64' | [ self-hosted, Linux ] | matches | +| 'self-hosted', 'Linux', 'X64' | [ self-hosted, X64 ] | matches | +| 'self-hosted', 'Linux', 'X64' | [ self-hosted, Linux, X64 ] | matches | +| 'self-hosted', 'Linux', 'X64' | other1 | no match | +| 'self-hosted', 'Linux', 'X64' | [ self-hosted, other2 ] | no match | +| 'self-hosted', 'Linux', 'X64' | [ self-hosted, Linux, X64, other2 ] | no match | +| 'self-hosted', 'Linux', 'X64', 'custom3' | custom3 | matches | +| 'self-hosted', 'Linux', 'X64', 'custom3' | [ custom3, Linux ] | matches | +| 'self-hosted', 'Linux', 'X64', 'custom3' | [ custom3, X64 ] | matches | +| 'self-hosted', 'Linux', 'X64', 'custom3' | [ custom3, other7 ] | no match | + +If default labels are removed: + +| Runner Labels | Workflow runs-on: | Result | +| ------------- | ------------- | ------------- | +| 'custom5' | custom5 | matches | +| 'custom5' | self-hosted | no match | +| 'custom5' | Linux | no match | +| 'custom5' | [ self-hosted, Linux ] | no match | +| 'custom5' | [ custom5, self-hosted, Linux ] | no match | diff --git a/docs/ami-examples/index.md b/docs/ami-examples/index.md new file mode 100644 index 0000000000..23e5033161 --- /dev/null +++ b/docs/ami-examples/index.md @@ -0,0 +1 @@ +--8<-- "images/README.md" diff --git a/docs/assets/aws-architecture.dark.png b/docs/assets/aws-architecture.dark.png new file mode 100644 index 0000000000..d0d631bb9e Binary files /dev/null and b/docs/assets/aws-architecture.dark.png differ diff --git a/docs/assets/aws-architecture.light.png b/docs/assets/aws-architecture.light.png new file mode 100644 index 0000000000..e51bb4fb30 Binary files /dev/null and b/docs/assets/aws-architecture.light.png differ diff --git a/docs/assets/diagrams.excalidraw b/docs/assets/diagrams.excalidraw new file mode 100644 index 0000000000..a3b403217a --- /dev/null +++ b/docs/assets/diagrams.excalidraw @@ -0,0 +1,15028 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "type": "rectangle", + "version": 2095, + "versionNonce": 1830578344, + "isDeleted": false, + "id": "ivE8803kNip-QGmVRPTJT", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 479.34950271953767, + "y": 238.1655044143024, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 426.74758746801734, + "height": 605.0866885921572, + "seed": 222552536, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "ZCy2IWtwus0Ua0-ZWtxiI", + "type": "arrow" + }, + { + "id": "CY9kqXcqCclWzV_SdZgnZ", + "type": "arrow" + } + ], + "updated": 1702808240664, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1694, + "versionNonce": 1337578968, + "isDeleted": false, + "id": "7RImS0Uks5cHJnYnzfxxf", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 813.0768506226378, + "y": 88.44567040205354, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 811559336, + "groupIds": [ + "y_nGoWXohv8-A0TmaqNv0", + "dC9F6UPDq95Gltle-mjNS", + "SA0uVnvbWnTy65JNmzMwW", + "IuygfmAxGBF9tpJQyWhQe", + "nP2Zt3NVVdQnN_JSLLuUk", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240664, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1396, + "versionNonce": 31003560, + "isDeleted": false, + "id": "R0smI5sVq2H9Cbtg0AVI7", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 821.2605020906659, + "y": 117.55234490545897, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 1192490152, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [ + { + "id": "3CctNqXoAGgfLtMVAW8GE", + "type": "arrow" + } + ], + "updated": 1702808240664, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1450, + "versionNonce": 1924225752, + "isDeleted": false, + "id": "fdgsnzLT1Q418ylxn_Drx", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 862.3182691402855, + "y": 117.47890981199313, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 1291788200, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240664, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2067, + "versionNonce": 1338531496, + "isDeleted": false, + "id": "1DAdqcBbGoUPPpD4RezW2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 838.2417234367086, + "y": 113.87194965096475, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1649207976, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240664, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2140, + "versionNonce": 913326040, + "isDeleted": false, + "id": "qQ_beEajJKiQLGEQMQORO", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5707963267948957, + "x": 844.8032191554468, + "y": 107.94479061787658, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1101616552, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240664, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2171, + "versionNonce": 1469467048, + "isDeleted": false, + "id": "ncQAr_lvHxK24aKaktGCM", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 850.7376230536948, + "y": 114.46363571690014, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1883267240, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2257, + "versionNonce": 1258980568, + "isDeleted": false, + "id": "bsfJ6nkZK4F_miZs121yM", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.71238898038469, + "x": 844.1852216277263, + "y": 120.41164963611024, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1841171368, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 1669, + "versionNonce": 611243176, + "isDeleted": false, + "id": "RsdpurV-PMn8EWbhqD0tZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 831.4051777696315, + "y": 121.62606969522673, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 1682855592, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 1685, + "versionNonce": 1041508824, + "isDeleted": false, + "id": "-kK8Wv8kCNYfG_mDCSz5S", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 853.9990263965693, + "y": 121.74894015686365, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 1486700968, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 1660, + "versionNonce": 2080243624, + "isDeleted": false, + "id": "5JEikMJ6-ymQ1So1DuAWk", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 825.2838960738615, + "y": 117.59616428797833, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 1507249320, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "line", + "version": 1764, + "versionNonce": 1252077272, + "isDeleted": false, + "id": "eLclIL4fqvQJytgWaiS6y", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 825.0302387008497, + "y": 142.28374796012938, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 833025960, + "groupIds": [ + "7FtbSz3Gv4I98y_835D1f", + "NyIjKGlqaz-duyOsmBgyJ", + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "text", + "version": 1824, + "versionNonce": 242207400, + "isDeleted": false, + "id": "9y31e3vEHEVxUCCei9ZTk", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 826.1172711548639, + "y": 157.68143796459114, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 38.41996765136719, + "height": 24, + "seed": 339329704, + "groupIds": [ + "_L4xJGQed9txa-M7PZZxl" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "B9LuEtI5fz0cIw_reMJMU", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "SQS", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "SQS", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 1581, + "versionNonce": 692425688, + "isDeleted": false, + "id": "2MGNA2z3GcTn0mTa2zdNs", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 539.2716510748435, + "y": 88.49848357063391, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.65338134765624, + "height": 64.65338134765624, + "seed": 1107504296, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "_pz_3_mcUDfEsFbLSG4mL", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2052, + "versionNonce": 644887976, + "isDeleted": false, + "id": "ftymM88T8ot4qojgFra_c", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 564.1681514203262, + "y": 108.59457909366009, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 15.16932105348633, + "height": 0, + "seed": 356997032, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 15.16932105348633, + 0 + ] + ] + }, + { + "type": "line", + "version": 2103, + "versionNonce": 1612011736, + "isDeleted": false, + "id": "YihJWICk_tAZZydVfmfrG", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 562.6962570668845, + "y": 133.37347361215623, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 17.13783740126311, + "height": 0, + "seed": 1691230888, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 17.13783740126311, + 0 + ] + ] + }, + { + "type": "line", + "version": 1949, + "versionNonce": 1496006824, + "isDeleted": false, + "id": "mwGTBXpM8hX3SfQAZ5o_V", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 545.8957074585726, + "y": 104.42391852712106, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 16.95504631353927, + "height": 48.41270068259871, + "seed": 1329827240, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 16.95504631353927, + -7.400560664373661 + ], + [ + 16.871549804500688, + 41.01214001822505 + ], + [ + 0.08056087780811456, + 33.450908214315675 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 1897, + "versionNonce": 312770008, + "isDeleted": false, + "id": "vUWAgl7oe9ujJ0Af8Hz5w", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 580.3567511378724, + "y": 96.83830706791403, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 16.976775286010504, + "height": 48.27905988118746, + "seed": 1037277352, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.1970252545028261, + 48.27905988118746 + ], + [ + 16.961573619999825, + 40.954321999069336 + ], + [ + 16.976775286010504, + 7.507893438730637 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 1622, + "versionNonce": 911010728, + "isDeleted": false, + "id": "BWlVTvVsGqHkre1N0ex-D", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 567.0377193513871, + "y": 126.9739466306103, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 9.101119485207235, + "height": 12.203935908273408, + "seed": 338314152, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 9.101119485207235, + -12.203935908273408 + ] + ] + }, + { + "type": "line", + "version": 1740, + "versionNonce": 1376191192, + "isDeleted": false, + "id": "h1r_y0iCPm5fypCnxFJR6", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 574.846233356194, + "y": 117.10519271216688, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.016669064250991, + "height": 8.41385706862771, + "seed": 1618185896, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.00572174417704, + 4.3706612125143 + ], + [ + -0.010947320073949565, + 8.41385706862771 + ] + ] + }, + { + "type": "line", + "version": 1880, + "versionNonce": 2013345448, + "isDeleted": false, + "id": "-bWj2kIQPE-LPB0Fq9iyq", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 563.0404167550616, + "y": 116.56180935941646, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.016669064250991, + "height": 8.41385706862771, + "seed": 190544296, + "groupIds": [ + "6vxts7OvGjaW-ZZxrnkat", + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.00572174417704, + 4.3706612125143 + ], + [ + -0.010947320073949565, + 8.41385706862771 + ] + ] + }, + { + "type": "text", + "version": 1566, + "versionNonce": 1825630168, + "isDeleted": false, + "id": "nouaLqy30cmJma63t5jm9", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 504.84837989564426, + "y": 156.55959873252849, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 133.4999237060547, + "height": 24, + "seed": 135136424, + "groupIds": [ + "QFqEmW0o-xXhIcScO4wsP" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "API Gateway", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "API Gateway", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2144, + "versionNonce": 854860200, + "isDeleted": false, + "id": "VprgBUfB4-wBA0Fq7V3Z1", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 684.1322650755469, + "y": 87.11727977715546, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 425350360, + "groupIds": [ + "ShLIPTUfjYrkmKHQqx7yP", + "yDpZlRcqQCVvE0h4RUJ7y", + "5QLX2RWefkTec-C2zuawB" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "3CctNqXoAGgfLtMVAW8GE", + "type": "arrow" + }, + { + "id": "_pz_3_mcUDfEsFbLSG4mL", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1308, + "versionNonce": 1058417880, + "isDeleted": false, + "id": "-MEaP4XIB7AILlZcnppYG", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 709.123472625994, + "y": 113.85474556225418, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.307143399999998, + "height": 26.897, + "seed": 1374288344, + "groupIds": [ + "PQtQjvNQqhfBJ0jVLJQ5o", + "yDpZlRcqQCVvE0h4RUJ7y", + "5QLX2RWefkTec-C2zuawB" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.576797599999999, + 13.180999999999997 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 1308, + "versionNonce": 106015912, + "isDeleted": false, + "id": "mkqF2UjARON9QMM065x5D", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 733.6101928259941, + "y": 129.75174556225411, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 54329048, + "groupIds": [ + "PQtQjvNQqhfBJ0jVLJQ5o", + "yDpZlRcqQCVvE0h4RUJ7y", + "5QLX2RWefkTec-C2zuawB" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 1643, + "versionNonce": 40554968, + "isDeleted": false, + "id": "XBJwc2PiBdYUxANHdIDyr", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 678.8328806257011, + "y": 156.48010936193842, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 75.05992126464844, + "height": 24, + "seed": 2112316376, + "groupIds": [ + "5QLX2RWefkTec-C2zuawB" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "webhook", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "webhook", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2315, + "versionNonce": 1271257000, + "isDeleted": false, + "id": "n9qmPQ5oyMHvQSgbGrMne", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 732.9139550675216, + "y": 690.1506164576085, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 2108843688, + "groupIds": [ + "8JP3DmWqQLEowGhF21mHF", + "NGCM2IzejF0oKKTKd2cxh", + "CLpHEk8i4ByssjrljWQcV" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "9ABOs5-WXUCCZ-D8t85bL", + "type": "arrow" + }, + { + "id": "h_B89cGbWb6iNZ006NPoL", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1480, + "versionNonce": 501405400, + "isDeleted": false, + "id": "Jr8uzD-U6dl_v26Xh5uV7", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 757.9051626179687, + "y": 716.8880822427072, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.428237149999962, + "height": 26.897, + "seed": 1258246568, + "groupIds": [ + "yLPPZ-sRI2Yo4BPCXrJew", + "NGCM2IzejF0oKKTKd2cxh", + "CLpHEk8i4ByssjrljWQcV" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.6978913499999635, + 13.18100000000004 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 1479, + "versionNonce": 1199350440, + "isDeleted": false, + "id": "clZMA_DffzhG1siO0jPPx", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 782.3918828179687, + "y": 732.7850822427072, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 1433853096, + "groupIds": [ + "yLPPZ-sRI2Yo4BPCXrJew", + "NGCM2IzejF0oKKTKd2cxh", + "CLpHEk8i4ByssjrljWQcV" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 1811, + "versionNonce": 1980906456, + "isDeleted": false, + "id": "7QzxA6f4rmUNTwy2wEsQO", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 746.5045547485352, + "y": 759.5134460423915, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 37.27995300292969, + "height": 24, + "seed": 1589970856, + "groupIds": [ + "CLpHEk8i4ByssjrljWQcV" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "pool", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "pool", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 3581, + "versionNonce": 1478626728, + "isDeleted": false, + "id": "3_YliClQBodWJoWEXxaHg", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 756.627866822027, + "y": 337.46828419801307, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1845818840, + "groupIds": [ + "0LI0NMCbkiF2e8fLaJbzw", + "OF0bfROP1LbzhR5BchF_F", + "3oCrT4kx6KXdMsjsqHj-u" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "B9LuEtI5fz0cIw_reMJMU", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2746, + "versionNonce": 1024262360, + "isDeleted": false, + "id": "9gHdU3snTfv9-xDkVYTyu", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 781.6190743724742, + "y": 364.2057499831118, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.307143399999998, + "height": 26.897, + "seed": 1519942360, + "groupIds": [ + "OGG2IV_GHyav7_G1corrw", + "OF0bfROP1LbzhR5BchF_F", + "3oCrT4kx6KXdMsjsqHj-u" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.576797599999999, + 13.180999999999997 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 2746, + "versionNonce": 652351656, + "isDeleted": false, + "id": "g6oBcd0Zy0KhEPqIj_ret", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 806.1057945724742, + "y": 380.1027499831117, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 1416847320, + "groupIds": [ + "OGG2IV_GHyav7_G1corrw", + "OF0bfROP1LbzhR5BchF_F", + "3oCrT4kx6KXdMsjsqHj-u" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 3090, + "versionNonce": 1114056152, + "isDeleted": false, + "id": "W6naSg5WGUxkEWtp9fIKN", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 748.9184863394664, + "y": 406.831113782796, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 79.87991333007812, + "height": 24, + "seed": 2074715352, + "groupIds": [ + "3oCrT4kx6KXdMsjsqHj-u" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "CY9kqXcqCclWzV_SdZgnZ", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "scale-up", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "scale-up", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 698, + "versionNonce": 1466483624, + "isDeleted": false, + "id": "XSH1imzmjT188KHXjPreK", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 510.1640625, + "y": 625.1640625, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 340.17578124999994, + "height": 183.87890625000006, + "seed": 149225176, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 195, + "versionNonce": 1127525080, + "isDeleted": false, + "id": "yJsb_vIWVuMD4e55A00Wu", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 655.5703125, + "y": 633, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 52.19197082519531, + "height": 35, + "seed": 1573070504, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "pool", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "pool", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 3112, + "versionNonce": 937561768, + "isDeleted": false, + "id": "ckHQnZo6y_sITM7X4uOh2", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 744.8633553545482, + "y": 947.6493909707428, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1242110424, + "groupIds": [ + "OAISmfJnEgFN2TFauQpF9", + "zkJxFQAxZED0le33uPVEk", + "hZNhZtFgv4U09ZQ_Ka3wZ" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "6iO3ZeCIQ2iX8l7aF1W0f", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2278, + "versionNonce": 973705176, + "isDeleted": false, + "id": "Wnt6UoYYk2dKuDxmY7AiQ", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 769.8545629049953, + "y": 974.3868567558416, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.428237149999962, + "height": 26.897, + "seed": 1786257112, + "groupIds": [ + "XZ7bK7ud2pNq3P1Hw9cv9", + "zkJxFQAxZED0le33uPVEk", + "hZNhZtFgv4U09ZQ_Ka3wZ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.6978913499999635, + 13.18100000000004 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 2277, + "versionNonce": 1895430568, + "isDeleted": false, + "id": "BqPGAOBhODnVDFI1LAiL6", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 794.3412831049953, + "y": 990.2838567558415, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 280921048, + "groupIds": [ + "XZ7bK7ud2pNq3P1Hw9cv9", + "zkJxFQAxZED0le33uPVEk", + "hZNhZtFgv4U09ZQ_Ka3wZ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 2616, + "versionNonce": 788124888, + "isDeleted": false, + "id": "_8Uwk3GYyo6czR-IQVJe0", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 719.5240005067532, + "y": 1017.0122205555258, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 115.13986206054688, + "height": 24, + "seed": 1257261272, + "groupIds": [ + "hZNhZtFgv4U09ZQ_Ka3wZ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "housekeeper", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "housekeeper", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 1602, + "versionNonce": 903644328, + "isDeleted": false, + "id": "AHmYgg_6BXpinuCIEB5W8", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 484.932737397741, + "y": 881.1619868362941, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 421.3225882902522, + "height": 183.87890625000006, + "seed": 1928556248, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1011, + "versionNonce": 127498712, + "isDeleted": false, + "id": "WfmHYbTmQnd-jav83Am-I", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 589.6097472718899, + "y": 890.4987745131343, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 208.01190185546875, + "height": 35, + "seed": 223335384, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "ssm housekeepr", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "ssm housekeepr", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 3067, + "versionNonce": 1949675432, + "isDeleted": false, + "id": "vv1ewWvR1lmII3MPO4kSQ", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 748.5951349836073, + "y": 464.98116784121976, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1898061528, + "groupIds": [ + "cMCNiKWRS1X0mk8MezbiY", + "yZtURJpNXBjW0I4EYrkiQ", + "HLTphb7UExmVC-JmKmNBz" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "A0Q4ehpvRidAU5HGJoEUB", + "type": "arrow" + }, + { + "id": "ztTiOSNqcEkLEIthcdd1V", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2231, + "versionNonce": 1459388120, + "isDeleted": false, + "id": "StjAXQX5l0qEpDjPFlkEq", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 773.5863425340544, + "y": 491.7186336263185, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.307143399999998, + "height": 26.897, + "seed": 841515992, + "groupIds": [ + "Uq3jIqdCYS_P2GxIELiF9", + "yZtURJpNXBjW0I4EYrkiQ", + "HLTphb7UExmVC-JmKmNBz" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.576797599999999, + 13.180999999999997 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 2231, + "versionNonce": 70351528, + "isDeleted": false, + "id": "npQTgc_zxibgOMM2u1d5U", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 798.0730627340545, + "y": 507.6156336263184, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 790251736, + "groupIds": [ + "Uq3jIqdCYS_P2GxIELiF9", + "yZtURJpNXBjW0I4EYrkiQ", + "HLTphb7UExmVC-JmKmNBz" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 2569, + "versionNonce": 766960600, + "isDeleted": false, + "id": "P_pix3ualaD7uv4Uoaiea", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 729.5057572476287, + "y": 534.3439974260027, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 102.63990783691406, + "height": 24, + "seed": 327904728, + "groupIds": [ + "HLTphb7UExmVC-JmKmNBz" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "scale-down", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "scale-down", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 3667, + "versionNonce": 1484514728, + "isDeleted": false, + "id": "bseMzya9y50b8CCr1bgn-", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1169.620160005523, + "y": 945.2974839301178, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 794661288, + "groupIds": [ + "r937UJfKgHIGjQMNSNxDq", + "rSGB1Elg5w56vBfSOPLly", + "vvSrZiUkleGLnEO9hx_pp" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "sB1bSldBW6W9Ael4sGSCI", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2833, + "versionNonce": 1776068824, + "isDeleted": false, + "id": "STWG8p8UfJQXblR4zR4M5", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1194.6113675559702, + "y": 972.0349497152165, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.428237149999962, + "height": 26.897, + "seed": 336403624, + "groupIds": [ + "8Im7CNDUrx9vmSAaMe07R", + "rSGB1Elg5w56vBfSOPLly", + "vvSrZiUkleGLnEO9hx_pp" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.6978913499999635, + 13.18100000000004 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 2832, + "versionNonce": 776007848, + "isDeleted": false, + "id": "bpcq-rDpAWC9ZyKWBVJ7C", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1219.0980877559703, + "y": 987.9319497152164, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 1888700328, + "groupIds": [ + "8Im7CNDUrx9vmSAaMe07R", + "rSGB1Elg5w56vBfSOPLly", + "vvSrZiUkleGLnEO9hx_pp" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 3171, + "versionNonce": 117558744, + "isDeleted": false, + "id": "94azACXceq5CjwbljpM5P", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1147.4307761660289, + "y": 1014.6603135149007, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 108.83992004394531, + "height": 24, + "seed": 1360794280, + "groupIds": [ + "vvSrZiUkleGLnEO9hx_pp" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "ami cleaner", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "ami cleaner", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2468, + "versionNonce": 1026333608, + "isDeleted": false, + "id": "rD9x8htS8yDcdXCoDaVZP", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 946.4162287290414, + "y": 882.8081428717896, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 359.3273862376628, + "height": 183.87890625000006, + "seed": 2078985384, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1491, + "versionNonce": 1849316056, + "isDeleted": false, + "id": "7G9Uz4JY0ei-UtRbK-s6v", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 1039.010104708704, + "y": 892.82598861207, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 152.37594604492188, + "height": 35, + "seed": 1899689896, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "ami cleaner", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "ami cleaner", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 418, + "versionNonce": 1735059112, + "isDeleted": false, + "id": "aBarJtrJNvnZRZVCZBw85", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 602.3927193330521, + "y": 252.90200709571934, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 175.6159210205078, + "height": 35, + "seed": 661564376, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "control plane", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "control plane", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 1713, + "versionNonce": 1176123352, + "isDeleted": false, + "id": "JPqW94G_1U4n_Rtp1AVB3", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 546.4665031650303, + "y": 464.7469773742682, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.70089111328099, + "height": 64.70089111328099, + "seed": 219969240, + "groupIds": [ + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "ztTiOSNqcEkLEIthcdd1V", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1924, + "versionNonce": 1772605864, + "isDeleted": false, + "id": "VGF8bIi6xAFr0yK8zfGi8", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 564.6166234707044, + "y": 497.3290115403506, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 29.0965264804551, + "height": 25.394020168765657, + "seed": 219667416, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.263070773388013, + -12.655407976268592 + ], + [ + 21.749092160923496, + -12.570519846452996 + ], + [ + 29.0965264804551, + 0.07090797495479251 + ], + [ + 21.970571387274813, + 12.415835859067506 + ], + [ + 7.3574223926479565, + 12.738612192497058 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 1708, + "versionNonce": 1119190232, + "isDeleted": false, + "id": "-y3H6G5z3EhPYnz4S6jJg", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 564.3499933276972, + "y": 474.14193324044527, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 576626904, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1769, + "versionNonce": 185556136, + "isDeleted": false, + "id": "X5Ts167GXBARvQ5P5C50E", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 569.4351448238818, + "y": 480.3007422695173, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 1283769816, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1830, + "versionNonce": 1973428696, + "isDeleted": false, + "id": "jKpZGn7XbcQEk1Tv330No", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 587.4277903570356, + "y": 513.5258642149297, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 2023639768, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1898, + "versionNonce": 1296926632, + "isDeleted": false, + "id": "bmTeP5TMWRhXtxFY6ts2T", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 586.4396478314517, + "y": 509.7288620234708, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 1363095512, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1841, + "versionNonce": 502146776, + "isDeleted": false, + "id": "NFdV9DtKYMrmTggIGQ7sY", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 593.055757430821, + "y": 483.7042306422859, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 242971864, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1929, + "versionNonce": 479089320, + "isDeleted": false, + "id": "Fx5LhCJoCs_p1pSdS18uG", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 558.2801563123268, + "y": 504.1071624131064, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 1172773336, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1735, + "versionNonce": 2016644056, + "isDeleted": false, + "id": "6f_9q-1sNX6NIY_Kaxl0O", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 579.2372005701274, + "y": 478.5387653859052, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 982916824, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1723, + "versionNonce": 2138946984, + "isDeleted": false, + "id": "SCbt1w8c8z-2EQByKimj9", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 596.0332051743109, + "y": 507.132982016999, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 756843480, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "line", + "version": 1908, + "versionNonce": 243552472, + "isDeleted": false, + "id": "NJPaEp7vDCTJZClqPCB8K", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 563.5156325055833, + "y": 510.0226170767014, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 730745048, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1893, + "versionNonce": 1195886760, + "isDeleted": false, + "id": "gQPcjuUXysUIrJnd7MLgN", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 556.2408110579414, + "y": 504.77895737816107, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 1635741144, + "groupIds": [ + "wPMijb20ufUzYgfg9uyo-", + "Va5cqnU2p1j9RSVB50IW4", + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "text", + "version": 2707, + "versionNonce": 141850072, + "isDeleted": false, + "id": "yBnwnAw_zdatclUTGwtJS", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 544.5927520798421, + "y": 532.4705649303639, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 68.63992309570312, + "height": 24, + "seed": 1745089240, + "groupIds": [ + "4UrRL00pHnWCa-3sPTfEd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Trigger", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Trigger", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2175, + "versionNonce": 1066955688, + "isDeleted": false, + "id": "kQEs74aFmFnjuSm-p72OE", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 485.24070390118686, + "y": 23.986293115700533, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 417.08299473498556, + "height": 187.37463292503452, + "seed": 851295960, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "5n_B9CJuQSbh_9oqVzuI6", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 2692, + "versionNonce": 1962781096, + "isDeleted": false, + "id": "QCFLMT1NgywylWWTmkOYg", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1161.4685373436992, + "y": 399.406761456999, + "strokeColor": "#000000", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1887237848, + "groupIds": [ + "UAfKw75GG1Xu4d3Q7cb2d", + "3U-JAbx9zmcDVF8p_rOfu", + "Q0YkJqpRrrtUEVbrYYeMR" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 2057, + "versionNonce": 575218904, + "isDeleted": false, + "id": "hgeszLpLEdL2TpjTTB5ir", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1183.2546665715317, + "y": 420.612963523125, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 21.136985907710482, + "height": 21.58982944276917, + "seed": 812145624, + "groupIds": [ + "-iYqz0gDkCHC_wRKJ3o4w", + "3U-JAbx9zmcDVF8p_rOfu", + "Q0YkJqpRrrtUEVbrYYeMR" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2382, + "versionNonce": 1575629992, + "isDeleted": false, + "id": "7T9SJIO0wAojoTiuird4D", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.726840450960482, + "x": 1194.3345514815724, + "y": 438.61511180723073, + "strokeColor": "#000", + "backgroundColor": "#ff00", + "width": 21.298113442520282, + "height": 21.325685740313624, + "seed": 127869144, + "groupIds": [ + "Cq10T91BOr1Jade3-93zF", + "-iYqz0gDkCHC_wRKJ3o4w", + "3U-JAbx9zmcDVF8p_rOfu", + "Q0YkJqpRrrtUEVbrYYeMR" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.05533508667380005, + -8.330350296057105 + ], + [ + -21.16993868276674, + -8.49388689455444 + ], + [ + -21.242778355846482, + 12.60784310791851 + ], + [ + -12.973972126229569, + 12.831798845759185 + ] + ] + }, + { + "type": "line", + "version": 2395, + "versionNonce": 1954466264, + "isDeleted": false, + "id": "kS-XSu9H2C3sQECgj8Xvo", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5503909961083693, + "x": 1212.8639938539063, + "y": 419.8449657513188, + "strokeColor": "#000", + "backgroundColor": "#ff00", + "width": 21.298113442520286, + "height": 21.325685740313624, + "seed": 901072344, + "groupIds": [ + "Pcfeve8dRlj9ZyIhcOSTI", + "-iYqz0gDkCHC_wRKJ3o4w", + "3U-JAbx9zmcDVF8p_rOfu", + "Q0YkJqpRrrtUEVbrYYeMR" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.05533508667380005, + -8.330350296057105 + ], + [ + -21.16993868276674, + -8.49388689455444 + ], + [ + -21.242778355846482, + 12.60784310791851 + ], + [ + -12.973972126229569, + 12.831798845759185 + ] + ] + }, + { + "type": "text", + "version": 2481, + "versionNonce": 789405608, + "isDeleted": false, + "id": "H1JUqEpOsA-BXGqT8J5ou", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1155.868150828755, + "y": 469.7377525538675, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 73.99993896484375, + "height": 24, + "seed": 1740557016, + "groupIds": [ + "Q0YkJqpRrrtUEVbrYYeMR" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Runners", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Runners", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 3550, + "versionNonce": 448253656, + "isDeleted": false, + "id": "nV1Lv6Z9RwU1kyPtg_KkZ", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1100.151062696964, + "y": 85.32476544310845, + "strokeColor": "#1971c2", + "backgroundColor": "#fd7e1488", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1243977688, + "groupIds": [ + "HrOK9xnIrqpZDjNY15sJV", + "VhBZf9TgEtPMXXjE_Cf00", + "D2cxMaMN_iRlzzPzzRYUj" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "vEz4-_ilsOBuVZj_DPvkJ", + "type": "arrow" + }, + { + "id": "dySicUMsQbgCIoOX-MYqw", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2715, + "versionNonce": 1754475176, + "isDeleted": false, + "id": "hbRcIE6hV2WuZL1kpH7to", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1125.142270247411, + "y": 112.06223122820717, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 19.428237149999962, + "height": 26.897, + "seed": 1851055320, + "groupIds": [ + "Y85PBWpbrBkDNy3q3Leuv", + "VhBZf9TgEtPMXXjE_Cf00", + "D2cxMaMN_iRlzzPzzRYUj" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.6978913499999635, + 13.18100000000004 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 2714, + "versionNonce": 2106078168, + "isDeleted": false, + "id": "H8gEOn5JgV8AN9i2Klf4E", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1149.628990447411, + "y": 127.9592312282071, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 911442392, + "groupIds": [ + "Y85PBWpbrBkDNy3q3Leuv", + "VhBZf9TgEtPMXXjE_Cf00", + "D2cxMaMN_iRlzzPzzRYUj" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "text", + "version": 3042, + "versionNonce": 623351208, + "isDeleted": false, + "id": "luOJrqF-VEM16PFV6uUdw", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1095.9516614624501, + "y": 154.6875950278914, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 72.85995483398438, + "height": 24, + "seed": 825591512, + "groupIds": [ + "D2cxMaMN_iRlzzPzzRYUj" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Lambda", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Lambda", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2269, + "versionNonce": 1392769240, + "isDeleted": false, + "id": "RRaBTf5MmJItGav7KoKS3", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 936.2349679689937, + "y": 28.711660708506486, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 392.07386041675875, + "height": 180.2379867547818, + "seed": 1184115928, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1425, + "versionNonce": 1240899752, + "isDeleted": false, + "id": "9UGnBJP6xfGlrJBqepXGl", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 1034.152519119069, + "y": 32.906678713288215, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 146.38394165039062, + "height": 35, + "seed": 1781060056, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "agent sync", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "agent sync", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 1729, + "versionNonce": 1858018776, + "isDeleted": false, + "id": "8QyXjCc6fidxs71LCPSST", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 648.4473726935557, + "y": 32.495975914416476, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 105.08393859863281, + "height": 35, + "seed": 2001795752, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "webhook", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "webhook", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 1400, + "versionNonce": 917261224, + "isDeleted": false, + "id": "U2pwmC5ui2QgIyOhovNXp", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1220.5108281030691, + "y": 84.23660394291932, + "strokeColor": "#000000", + "backgroundColor": "#40c05788", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 457922472, + "groupIds": [ + "mg07ugnqgkBXJlWPzZ0VR", + "8o4pTqp1y0qDkDDpxrId8", + "LbdWIkAUaDfIkGbV2qtSl", + "4P1hbLOVsiiEENh-TqOKq" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "dySicUMsQbgCIoOX-MYqw", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1187, + "versionNonce": 298689240, + "isDeleted": false, + "id": "S2fRHltGa41rWJQlVHhQo", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1234.123683280728, + "y": 95.30369996843496, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 39.10563151041674, + "height": 10.753995455228363, + "seed": 173154984, + "groupIds": [ + "LbdWIkAUaDfIkGbV2qtSl", + "4P1hbLOVsiiEENh-TqOKq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1805, + "versionNonce": 1970575016, + "isDeleted": false, + "id": "Y1HZpABlGLQA_pf7sRtlf", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1234.4815996969944, + "y": 101.18216801731381, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 38.295773237179446, + "height": 40.48662140675077, + "seed": 608669096, + "groupIds": [ + "LbdWIkAUaDfIkGbV2qtSl", + "4P1hbLOVsiiEENh-TqOKq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 3.8452774439103905, + 32.14685684595355 + ], + [ + 6.768312737880933, + 37.98883103590748 + ], + [ + 20.34867663261207, + 40.48662140675077 + ], + [ + 32.537268066406114, + 38.400380608974274 + ], + [ + 35.36686823918285, + 31.944173177083314 + ], + [ + 38.295773237179446, + 0.09767190004004078 + ] + ] + }, + { + "type": "ellipse", + "version": 1197, + "versionNonce": 985892824, + "isDeleted": false, + "id": "MUtN_U_-mu6CxKPWRmoCX", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1251.251887782932, + "y": 111.44466719568612, + "strokeColor": "#000000", + "backgroundColor": "#000", + "width": 4.69818115234375, + "height": 4.69818115234375, + "seed": 1381472424, + "groupIds": [ + "LbdWIkAUaDfIkGbV2qtSl", + "4P1hbLOVsiiEENh-TqOKq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1883, + "versionNonce": 1794867624, + "isDeleted": false, + "id": "S2lL80cWoxZX1EMQULVUP", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1253.742006191135, + "y": 114.01765761316659, + "strokeColor": "#000000", + "backgroundColor": "#000", + "width": 23.24691772460949, + "height": 11.53113708496096, + "seed": 2016297896, + "groupIds": [ + "LbdWIkAUaDfIkGbV2qtSl", + "4P1hbLOVsiiEENh-TqOKq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.0229309082030795, + 7.4353179931640625 + ], + [ + 17.00493774414076, + 11.53113708496096 + ], + [ + 22.923687744140693, + 10.143841552734386 + ], + [ + 23.24691772460949, + 5.890612792968767 + ], + [ + 17.962628173828193, + 1.7561248779296932 + ] + ] + }, + { + "type": "text", + "version": 1647, + "versionNonce": 270593527, + "isDeleted": false, + "id": "Ld5s9wIHR4OgCg_sIod_y", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1201.2012883081472, + "y": 153.40684854564222, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 103.69992065429688, + "height": 24, + "seed": 603426472, + "groupIds": [ + "4P1hbLOVsiiEENh-TqOKq" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324882, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "S3 Bucket", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "S3 Bucket", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 3478, + "versionNonce": 107809960, + "isDeleted": false, + "id": "0-WIPIwbxU5oirOXK2PXz", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 1053.0718064627845, + "y": 240.16684651719345, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 265.7672270276938, + "height": 342.04923291144314, + "seed": 301402840, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "CY9kqXcqCclWzV_SdZgnZ", + "type": "arrow" + }, + { + "id": "A0Q4ehpvRidAU5HGJoEUB", + "type": "arrow" + }, + { + "id": "9ABOs5-WXUCCZ-D8t85bL", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1003, + "versionNonce": 741700056, + "isDeleted": false, + "id": "2PR1c1kEdJvHW4dUttDgb", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 1096.3899056611824, + "y": 266.52623911901105, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 189.25193786621094, + "height": 35, + "seed": 369971928, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "vpc / subnets", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "vpc / subnets", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 3448, + "versionNonce": 1903507368, + "isDeleted": false, + "id": "OW-7NkHXdp3-DKfEoW3Ob", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 970.8908038758286, + "y": 754.1240411048966, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 160.07986450195312, + "height": 24, + "seed": 664832984, + "groupIds": [ + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "SSM parameters", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "SSM parameters", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 3615, + "versionNonce": 1968797400, + "isDeleted": false, + "id": "iZ02Q8fytYseReUFnZdfQ", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1018.7001599443267, + "y": 684.5878035737188, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1213288664, + "groupIds": [ + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 7672, + "versionNonce": 1077936808, + "isDeleted": false, + "id": "GMjdZwJb62aEmvt-ZWbJG", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1061.143301256325, + "y": 744.4791645723145, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 27.08452429530482, + "height": 28.76032398582327, + "seed": 10581464, + "groupIds": [ + "q91gJ4GdKDIfI-Za0nlt6", + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.8178346989934635, + 0.15014468903849598 + ], + [ + 5.689722111063916, + -2.930541448733268 + ], + [ + 9.123193867826467, + -4.861206308869573 + ], + [ + 11.875030496454142, + -2.8135809119822635 + ], + [ + 15.822856613672839, + -7.579858785209758 + ], + [ + 13.153164362019155, + -9.512971656580397 + ], + [ + 13.91068783841809, + -12.619497912936685 + ], + [ + 17.155662730137735, + -12.608073860509842 + ], + [ + 17.162462761344187, + -18.169683383644127 + ], + [ + 14.062464534946132, + -18.1634273549342 + ], + [ + 12.764202577009984, + -20.367725470818193 + ], + [ + 14.830868061275366, + -23.210682517612337 + ], + [ + 10.917586102585439, + -26.76601083359455 + ], + [ + 8.72852005660387, + -24.373759855164163 + ], + [ + 6.257388716178699, + -25.45904483571416 + ], + [ + 6.430925512567352, + -28.50246680247455 + ], + [ + 1.1361492139742917, + -28.61017929678477 + ], + [ + 1.0417647808286912, + -25.70656597162907 + ], + [ + -1.1162931228514479, + -24.532336582898658 + ], + [ + -3.7307691211086893, + -26.93981963123151 + ], + [ + -7.741699527923323, + -22.9223611944587 + ], + [ + -5.518633325909507, + -21.06948869132421 + ], + [ + -6.807919242653169, + -18.442500635647054 + ], + [ + -9.692220479182536, + -18.27630787296132 + ], + [ + -9.922061533960633, + -12.81343480294472 + ], + [ + -7.2194571312677125, + -12.869739061334164 + ], + [ + -6.187212394128019, + -9.746348727585874 + ], + [ + -8.752184165202326, + -8.174997516398578 + ], + [ + -5.233304016486706, + -3.2479669054505185 + ], + [ + -2.5516437099096714, + -4.8565822876491955 + ], + [ + 0.06500829833369015, + -3.287679087696215 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "arrow", + "version": 3639, + "versionNonce": 1706351576, + "isDeleted": false, + "id": "Ttx3BS8Zm8u6mkgoYxVyM", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1060.7706005074222, + "y": 723.514433019078, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 10.460082855905723, + "height": 5.397560826503627, + "seed": 1705310936, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": { + "elementId": "Q8RH9f9ZETUTnqeD9cupi", + "focus": 2.3761205074924336, + "gap": 13.507291055437861 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 1.9602269710062705, + 0.12178820829017356 + ], + [ + 7.235999589219723, + 0.7079851658694465 + ], + [ + 10.460082855905723, + 5.397560826503627 + ] + ] + }, + { + "type": "arrow", + "version": 1907, + "versionNonce": 561606056, + "isDeleted": false, + "id": "FZpOHAiKm4czwU_PV5FAg", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1058.4808995359788, + "y": 734.9048109543447, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 12.60323458795436, + "height": 5.275772618213453, + "seed": 1240457176, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 4.103378703054907, + -3.5171817454756353 + ], + [ + 9.37915132126836, + -2.9309847878963624 + ], + [ + 12.60323458795436, + 1.7585908727378177 + ] + ] + }, + { + "type": "line", + "version": 1973, + "versionNonce": 1599840472, + "isDeleted": false, + "id": "ZGQtou6iTsBJe3NVqFhyM", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1044.8518202722607, + "y": 733.0153725486517, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 48.947445957869256, + "height": 44.25787029723508, + "seed": 227943640, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -21.68928743043308, + 0 + ], + [ + -21.68928743043308, + -44.25787029723508 + ], + [ + 27.25815852743617, + -44.25787029723508 + ], + [ + 27.25815852743617, + -21.396188951643445 + ] + ] + }, + { + "type": "rectangle", + "version": 1841, + "versionNonce": 239958184, + "isDeleted": false, + "id": "-J5RVDxne57e5irCj-vNZ", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1027.559010023672, + "y": 702.533130754504, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 9.086052842478724, + "height": 4.68957566063418, + "seed": 1848363480, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1846, + "versionNonce": 1642186200, + "isDeleted": false, + "id": "xSl_YomczaJWd2whZonT5", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1042.946680160128, + "y": 710.153691203037, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 9.086052842478724, + "height": 4.68957566063418, + "seed": 1455738584, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "Ttx3BS8Zm8u6mkgoYxVyM", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1843, + "versionNonce": 2053645224, + "isDeleted": false, + "id": "-HewxDUsxcXIlP9-f0RGU", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1058.187801057189, + "y": 699.0159490090292, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 9.086052842478724, + "height": 4.68957566063418, + "seed": 804598744, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1848, + "versionNonce": 1515932376, + "isDeleted": false, + "id": "XsUQtpWkoH-O57chtw8tX", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1029.6106993751996, + "y": 707.2227064151376, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 4.982674139423816, + "height": 20.2237950364849, + "seed": 802224344, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1891, + "versionNonce": 66416296, + "isDeleted": false, + "id": "Q8RH9f9ZETUTnqeD9cupi", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1044.9983695116555, + "y": 692.1281347574724, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.275772618213453, + "height": 17.87900720616781, + "seed": 703339992, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "Ttx3BS8Zm8u6mkgoYxVyM", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1974, + "versionNonce": 1935421400, + "isDeleted": false, + "id": "YEmT8Pd4LMD7qs8OReOvA", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1029.6106993751996, + "y": 692.1281347574724, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 4.982674139423816, + "height": 10.258446757637268, + "seed": 1599775448, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 2035, + "versionNonce": 597776808, + "isDeleted": false, + "id": "Q-qxAGIIgzVDHWfiQW40M", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1060.2394904087166, + "y": 692.1281347574724, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 4.396477181844544, + "height": 7.034363490951271, + "seed": 1320191960, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1846, + "versionNonce": 1694004440, + "isDeleted": false, + "id": "VP6uK6lCZTnFceGN14s1M", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1044.8518202722607, + "y": 727.4465014516337, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 0, + "height": 12.017037630375086, + "seed": 67226840, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + -12.017037630375086 + ] + ] + }, + { + "type": "line", + "version": 1850, + "versionNonce": 1553458344, + "isDeleted": false, + "id": "P_-TNFDtfpwH8ICKJ6ulo", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1060.2394904087166, + "y": 711.6191835969859, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 0, + "height": 7.913658927320179, + "seed": 1759670744, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + -7.913658927320179 + ] + ] + }, + { + "type": "line", + "version": 1850, + "versionNonce": 1153702360, + "isDeleted": false, + "id": "kXQTwuoPNsxt9U_7cLrA_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1064.635967590561, + "y": 711.7657328363822, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 0, + "height": 7.913658927320179, + "seed": 342259416, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + -7.913658927320179 + ] + ] + }, + { + "type": "line", + "version": 1850, + "versionNonce": 1820659624, + "isDeleted": false, + "id": "0yApPNkAThs6bxoN_FdLb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1050.2741421298688, + "y": 715.576013060646, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 0, + "height": 2.6378863091067264, + "seed": 455203800, + "groupIds": [ + "3qJkYfwHH5q9gNLljz2X0", + "nHfOBTulMkt990-5QCCxo", + "o7NdDidZa2m1kmBOu8jRw" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 2.6378863091067264 + ] + ] + }, + { + "type": "rectangle", + "version": 1867, + "versionNonce": 1439899352, + "isDeleted": false, + "id": "uUv0KoFONcaKfwZdcWlGA", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 560.7333087440102, + "y": 687.535437004839, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.70089111328099, + "height": 64.70089111328099, + "seed": 1288439208, + "groupIds": [ + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "h_B89cGbWb6iNZ006NPoL", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2078, + "versionNonce": 2073352872, + "isDeleted": false, + "id": "pW97iRg031X16GdDoVXdt", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 578.8834290496843, + "y": 720.1174711709214, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 29.0965264804551, + "height": 25.394020168765657, + "seed": 1670189224, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.263070773388013, + -12.655407976268592 + ], + [ + 21.749092160923496, + -12.570519846452996 + ], + [ + 29.0965264804551, + 0.07090797495479251 + ], + [ + 21.970571387274813, + 12.415835859067506 + ], + [ + 7.3574223926479565, + 12.738612192497058 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 1862, + "versionNonce": 1488552920, + "isDeleted": false, + "id": "XoTLH8b60EmKzFLv3DiMS", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 578.6167989066771, + "y": 696.930392871016, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 871676840, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1923, + "versionNonce": 1282622888, + "isDeleted": false, + "id": "2aXXoYOdC8dSWnJBd4Rer", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 583.7019504028617, + "y": 703.089201900088, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 271517352, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1984, + "versionNonce": 1535854808, + "isDeleted": false, + "id": "1bDHlynlCftez5sj7-xDD", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 601.6945959360155, + "y": 736.3143238455004, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 619180456, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2052, + "versionNonce": 1816940712, + "isDeleted": false, + "id": "NfWCo_lvlsl3RB914mRlm", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 600.7064534104315, + "y": 732.5173216540416, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 692812968, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1995, + "versionNonce": 165440984, + "isDeleted": false, + "id": "xGRW1ujzzh7l7i2TYRjWl", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 607.3225630098009, + "y": 706.4926902728566, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 252028840, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2083, + "versionNonce": 1657535400, + "isDeleted": false, + "id": "LjSED6ByURVFQwgBGTMyK", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 572.5469618913066, + "y": 726.8956220436771, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 843215528, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1889, + "versionNonce": 2093019864, + "isDeleted": false, + "id": "DJlSJwOi7XFyzos4-YH98", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 593.5040061491072, + "y": 701.327225016476, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 162389416, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1877, + "versionNonce": 1646151336, + "isDeleted": false, + "id": "1tHUSVNSKXzCjsD5E3rUV", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 610.3000107532907, + "y": 729.9214416475697, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 1450436776, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "line", + "version": 2062, + "versionNonce": 181196760, + "isDeleted": false, + "id": "cwoOqvIF_xZ_CT9QkD4vc", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 577.7824380845632, + "y": 732.8110767072722, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 1413518248, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 2047, + "versionNonce": 1995387304, + "isDeleted": false, + "id": "Tq1-C0m7_K5AhRXFretPu", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 570.5076166369213, + "y": 727.5674170087318, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 1765793448, + "groupIds": [ + "Oqn85bUs0EawXZuHfBx9j", + "giaWLKAMEYOmky1lVDht1", + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "text", + "version": 2861, + "versionNonce": 403971288, + "isDeleted": false, + "id": "QABa7PO_kOVOrplOwkPDK", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 558.8595576588218, + "y": 755.2590245609347, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 68.63992309570312, + "height": 24, + "seed": 1444792744, + "groupIds": [ + "vJ8ImlZHJTcBom-bLhP5T" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Trigger", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Trigger", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 1741, + "versionNonce": 946519208, + "isDeleted": false, + "id": "9A9ymB7KBKZlxIU_b8X-p", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 576.6542592379991, + "y": 946.1504339116468, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.70089111328099, + "height": 64.70089111328099, + "seed": 1601291224, + "groupIds": [ + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "6iO3ZeCIQ2iX8l7aF1W0f", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1952, + "versionNonce": 1714078168, + "isDeleted": false, + "id": "-UNyGkl55A9Y9gOC-0DTc", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 594.8043795436732, + "y": 978.7324680777292, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 29.0965264804551, + "height": 25.394020168765657, + "seed": 1631291608, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.263070773388013, + -12.655407976268592 + ], + [ + 21.749092160923496, + -12.570519846452996 + ], + [ + 29.0965264804551, + 0.07090797495479251 + ], + [ + 21.970571387274813, + 12.415835859067506 + ], + [ + 7.3574223926479565, + 12.738612192497058 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 1736, + "versionNonce": 2017257384, + "isDeleted": false, + "id": "bh-ZNcT6Xl0n8np-7J8Fc", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 594.537749400666, + "y": 955.5453897778239, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 1870966232, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1797, + "versionNonce": 1680131800, + "isDeleted": false, + "id": "l3m9wzvWp8BKVDCpG0sJa", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 599.6229008968506, + "y": 961.7041988068959, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 56701656, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1858, + "versionNonce": 1922151080, + "isDeleted": false, + "id": "MFOMBTnY9cF9GnqX1uzIS", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 617.6155464300044, + "y": 994.9293207523083, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 1399134168, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1926, + "versionNonce": 2123770840, + "isDeleted": false, + "id": "W-fxa1IPkScZhf0Vg175k", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 616.6274039044205, + "y": 991.1323185608494, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 597974232, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1869, + "versionNonce": 2115313064, + "isDeleted": false, + "id": "-MVyqy1XOdnMy4v6kzqlb", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 623.2435135037898, + "y": 965.1076871796645, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 364052952, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1957, + "versionNonce": 1871900888, + "isDeleted": false, + "id": "RufA5AIuS42ixHd_8TxfU", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 588.4679123852956, + "y": 985.510618950485, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 2024081112, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1763, + "versionNonce": 1005791400, + "isDeleted": false, + "id": "Ez3CEvRYmawaI2nrKHlyf", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 609.4249566430962, + "y": 959.9422219232838, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 420375512, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1751, + "versionNonce": 246355416, + "isDeleted": false, + "id": "qoyiPJyFORLGD3_NK2URs", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 626.2209612472797, + "y": 988.5364385543776, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 285421784, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "line", + "version": 1936, + "versionNonce": 1205326760, + "isDeleted": false, + "id": "XryKjMTjt4YmYo4JpTfbs", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 593.7033885785521, + "y": 991.42607361408, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 404182488, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1921, + "versionNonce": 553556696, + "isDeleted": false, + "id": "xiN5r4BFKn3rJd1i3Mib8", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 586.4285671309102, + "y": 986.1824139155397, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 1398725336, + "groupIds": [ + "lpJV6Z0a2KnPK2saEFAbT", + "r0mdCdiL6QJu-lo7K716H", + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "text", + "version": 2735, + "versionNonce": 1743724200, + "isDeleted": false, + "id": "MVoyuSrpKDJYJAXdNBoHj", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 574.7805081528107, + "y": 1013.8740214677428, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 68.63992309570312, + "height": 24, + "seed": 627949528, + "groupIds": [ + "wpgu0JeD90ZuyECu9WhZJ" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Trigger", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Trigger", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2012, + "versionNonce": 689274840, + "isDeleted": false, + "id": "XDRmZYk2bUUh_OuCE_imI", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1013.9401410888256, + "y": 945.6829740206363, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.70089111328099, + "height": 64.70089111328099, + "seed": 1036816040, + "groupIds": [ + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "sB1bSldBW6W9Ael4sGSCI", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2223, + "versionNonce": 1021643176, + "isDeleted": false, + "id": "nQFZcVpSwjxV0MOrb0fHN", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1032.0902613944997, + "y": 978.2650081867187, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 29.0965264804551, + "height": 25.394020168765657, + "seed": 1435793832, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.263070773388013, + -12.655407976268592 + ], + [ + 21.749092160923496, + -12.570519846452996 + ], + [ + 29.0965264804551, + 0.07090797495479251 + ], + [ + 21.970571387274813, + 12.415835859067506 + ], + [ + 7.3574223926479565, + 12.738612192497058 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 2007, + "versionNonce": 923256024, + "isDeleted": false, + "id": "sPcrna6E_s5P5u_RIezYS", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1031.8236312514925, + "y": 955.0779298868133, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 589759656, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2068, + "versionNonce": 1910871208, + "isDeleted": false, + "id": "CznBse1bWLO5pCgiA79v6", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1036.9087827476772, + "y": 961.2367389158853, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 1412444072, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 2129, + "versionNonce": 946432472, + "isDeleted": false, + "id": "BYrZ712eY_xaUoZlQ1i7Z", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1054.901428280831, + "y": 994.4618608612977, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 14416552, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2197, + "versionNonce": 1822212008, + "isDeleted": false, + "id": "vRUP_A0Nd519FjYra1xhj", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1053.913285755247, + "y": 990.6648586698388, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 1540777384, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 2140, + "versionNonce": 1213099736, + "isDeleted": false, + "id": "KE775NJ3Vh5xIOosfBmuj", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1060.5293953546163, + "y": 964.6402272886539, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 1649111208, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2228, + "versionNonce": 2100726440, + "isDeleted": false, + "id": "DSk6gXgTJsuRZl3Yq_gFB", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1025.753794236122, + "y": 985.0431590594744, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 199695272, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2034, + "versionNonce": 2135610328, + "isDeleted": false, + "id": "7-1AoPipAIW2gSZdhf27P", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1046.7108384939227, + "y": 959.4747620322732, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 2060805800, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 2022, + "versionNonce": 241104296, + "isDeleted": false, + "id": "HJoYxMk3Bh-rRCABmhUQh", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1063.5068430981062, + "y": 988.068978663367, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 734155176, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "line", + "version": 2207, + "versionNonce": 1131583704, + "isDeleted": false, + "id": "E1kCXrip5WHS6223vh69g", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1030.9892704293786, + "y": 990.9586137230694, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 635034792, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 2192, + "versionNonce": 1430388904, + "isDeleted": false, + "id": "rBPHwiwHIJhg0z-oSljsB", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1023.7144489817367, + "y": 985.7149540245291, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 717752232, + "groupIds": [ + "9rficefRt2BpacKOlaAYo", + "Mgaeo1MxZ2b3jOGLKmHsQ", + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "text", + "version": 3006, + "versionNonce": 408534488, + "isDeleted": false, + "id": "PcSfvJ50qMCUrd3vSo38-", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1012.0663900036375, + "y": 1013.4065615767322, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 68.63992309570312, + "height": 24, + "seed": 1723388584, + "groupIds": [ + "LYxusaRPIoibUN9WqI81C" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Trigger", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Trigger", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 1802, + "versionNonce": 25930664, + "isDeleted": false, + "id": "t6kcifZDQhbV_nWUqOl38", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 983.0200647497404, + "y": 86.50416157572238, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.70089111328099, + "height": 64.70089111328099, + "seed": 1472657112, + "groupIds": [ + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "vEz4-_ilsOBuVZj_DPvkJ", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2013, + "versionNonce": 1863598808, + "isDeleted": false, + "id": "DFZjXOYckaEEaXsyKuFyE", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1001.1701850554145, + "y": 119.08619574180477, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 29.0965264804551, + "height": 25.394020168765657, + "seed": 510811096, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.263070773388013, + -12.655407976268592 + ], + [ + 21.749092160923496, + -12.570519846452996 + ], + [ + 29.0965264804551, + 0.07090797495479251 + ], + [ + 21.970571387274813, + 12.415835859067506 + ], + [ + 7.3574223926479565, + 12.738612192497058 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "ellipse", + "version": 1797, + "versionNonce": 1835529896, + "isDeleted": false, + "id": "kSle35CinQ1sA-sAST9fg", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1000.9035549124073, + "y": 95.89911744189942, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 610869464, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1858, + "versionNonce": 1983260632, + "isDeleted": false, + "id": "nCkcaJi-Gj6y-UXxHFq4R", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1005.988706408592, + "y": 102.05792647097144, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 692012504, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1919, + "versionNonce": 1300423080, + "isDeleted": false, + "id": "tq-vHrMslqGBEPZUr9cT-", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1023.9813519417457, + "y": 135.28304841638385, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 1510525656, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1987, + "versionNonce": 1775463640, + "isDeleted": false, + "id": "_-qjlYrFZMzp6WigV3Z42", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1022.9932094161618, + "y": 131.48604622492496, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.4300394358401154, + "height": 4.165241568829386, + "seed": 559525848, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.4300394358401154, + 4.165241568829386 + ] + ] + }, + { + "type": "ellipse", + "version": 1930, + "versionNonce": 1627942056, + "isDeleted": false, + "id": "BFv-mYDBgemf7btmHv84E", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1029.6093190155311, + "y": 105.46141484374004, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 2001073368, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2018, + "versionNonce": 1669337560, + "isDeleted": false, + "id": "IvExXLyv1TNrEB9_TCLJb", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 994.8337178970369, + "y": 125.86434661456053, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.527048406442323, + "height": 6.527048406442323, + "seed": 828479960, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1824, + "versionNonce": 564434856, + "isDeleted": false, + "id": "3-flS9_Dj1Dzx16JB31Ya", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1015.7907621548375, + "y": 100.29594958735936, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 1388355288, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1812, + "versionNonce": 709891800, + "isDeleted": false, + "id": "nkjlSKQnH-y7d2oCu3uVj", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1032.586766759021, + "y": 128.89016621845315, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 1542915032, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "line", + "version": 1997, + "versionNonce": 1937990312, + "isDeleted": false, + "id": "pw9G7hyNSDw_nEoI6AmxB", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 1000.0691940902934, + "y": 131.77980127815556, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 14.881064367630502, + "height": 5.819316836931806, + "seed": 454609112, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 10.971069476124091, + -0.03892935430490446 + ], + [ + 14.881064367630502, + 5.780387482626902 + ] + ] + }, + { + "type": "line", + "version": 1982, + "versionNonce": 47676376, + "isDeleted": false, + "id": "aR_rzj4KLztdvjax1gGpQ", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 992.7943726426515, + "y": 126.53614157961522, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.359881211089217, + "height": 17.609098804231238, + "seed": 2075782616, + "groupIds": [ + "UiYc3P4Sz4f2klJYSV7dR", + "J1L7NaF-KAKPeyL2x_fdK", + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.359881211089217, + -9.699887830271365 + ], + [ + 1.5123117765600742, + -17.609098804231238 + ] + ] + }, + { + "type": "text", + "version": 2796, + "versionNonce": 1431358888, + "isDeleted": false, + "id": "dFzpfPQIKSw4AWDzU8HVv", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 981.146313664552, + "y": 154.2277491318181, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 68.63992309570312, + "height": 24, + "seed": 1458467544, + "groupIds": [ + "BCaPcKNNCXAauw4HeNuzo" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "Trigger", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Trigger", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 3621, + "versionNonce": 2133475544, + "isDeleted": false, + "id": "-LhaEMrYv6CeKP6Y-Xj2R", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 173.95314709825846, + "y": 444.1192521427794, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 723526616, + "groupIds": [ + "eealDpUnuW39r_l6_aeyG", + "LWzQzJqG5tRL2J5yjpR0k", + "Um-Yeh9JqyAXu3ehdPPDy", + "PbUEi35G3YOyRBZQByKgf", + "EpFMqCfRgbyGV8R2hUwMn" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1577, + "versionNonce": 272160936, + "isDeleted": false, + "id": "OjLHq6b5pr-RJLnhmhb9K", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 180.24247189657683, + "y": 450.4914805060845, + "strokeColor": "#000000", + "backgroundColor": "#868e96", + "width": 51.88250276832002, + "height": 51.88250276832002, + "seed": 1746790616, + "groupIds": [ + "4p6r9UvdODle89IROy91k", + "EpFMqCfRgbyGV8R2hUwMn" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "5n_B9CJuQSbh_9oqVzuI6", + "type": "arrow" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 5122, + "versionNonce": 1323066840, + "isDeleted": false, + "id": "WxXQkBws6TARgF1xzTRht", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 195.99023582726306, + "y": 460.89953111564284, + "strokeColor": "#000000", + "backgroundColor": "#fff", + "width": 28.10264153823924, + "height": 32.45750960039449, + "seed": 723193304, + "groupIds": [ + "4p6r9UvdODle89IROy91k", + "EpFMqCfRgbyGV8R2hUwMn" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.522383435627326, + 0.8876695614221044 + ], + [ + 4.222250533550099, + 2.710891079770457 + ], + [ + 6.53876438289814, + 1.9494891881139838 + ], + [ + 13.00273268947289, + 2.0374391115495714 + ], + [ + 15.018859724261578, + 2.2364052653721083 + ], + [ + 16.578273739956423, + 0.9941438562971401 + ], + [ + 18.744233429245106, + -0.5092823311506232 + ], + [ + 19.3382730064762, + 1.5588921397895759 + ], + [ + 19.283438583962543, + 3.566556278350808 + ], + [ + 21.26661686487244, + 5.46749782452002 + ], + [ + 22.153106695509578, + 10.909367329014938 + ], + [ + 21.45853734367018, + 16.608727547781946 + ], + [ + 19.438802781084537, + 18.8230883820351 + ], + [ + 16.687942584983702, + 20.009258415382803 + ], + [ + 13.71774469882833, + 20.664602961087855 + ], + [ + 14.50370475485716, + 21.40308436092641 + ], + [ + 15.390194585494283, + 23.040424434305827 + ], + [ + 15.572975993873055, + 28.176226896819482 + ], + [ + 15.536419712197318, + 31.28569415677526 + ], + [ + 14.567678247789736, + 31.823854903738514 + ], + [ + 7.240428539404906, + 31.948227269243866 + ], + [ + 6.324236729906197, + 31.05132655929166 + ], + [ + 6.068342758175913, + 27.392989048505843 + ], + [ + 4.377614730672068, + 27.862931757494 + ], + [ + 1.5810591824765403, + 28.041957551394276 + ], + [ + -1.0327149573401755, + 26.542616527479623 + ], + [ + -2.659469491911409, + 23.92436429168835 + ], + [ + -4.240528674387946, + 22.313132146586064 + ], + [ + -5.949534842729662, + 21.179302118551103 + ], + [ + -3.628210956319009, + 21.40308436092641 + ], + [ + -1.9831782809098755, + 22.671183734386556 + ], + [ + -0.11880791544621871, + 24.43906344915162 + ], + [ + 2.147681548450816, + 25.543055844869823 + ], + [ + 4.660925913659192, + 25.22976070554441 + ], + [ + 5.9038394906349865, + 24.252578247172192 + ], + [ + 6.022647406081191, + 22.71594018286161 + ], + [ + 6.689799546663803, + 21.380706136688904 + ], + [ + 7.558011236463052, + 20.776494082275484 + ], + [ + 4.277084956063728, + 19.93358096932851 + ], + [ + 1.1423838023674477, + 18.89984919335192 + ], + [ + -0.4569535209469784, + 16.571430507386058 + ], + [ + -1.6541717458280658, + 10.963038997107194 + ], + [ + -0.7037084222583516, + 5.6861115380996985 + ], + [ + 0.6671521405825978, + 4.240069736001822 + ], + [ + -0.11880791544621871, + 2.2772861946741387 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "text", + "version": 2459, + "versionNonce": 1743225768, + "isDeleted": false, + "id": "hitiVDIgOP98amDOep0aJ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 173.68372328073758, + "y": 514.1185010342941, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 63.99993896484375, + "height": 50, + "seed": 1026265816, + "groupIds": [ + "EpFMqCfRgbyGV8R2hUwMn" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "GitHub\nApp", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "GitHub\nApp", + "lineHeight": 1.25, + "baseline": 43 + }, + { + "type": "arrow", + "version": 416, + "versionNonce": 251783896, + "isDeleted": false, + "id": "ZCy2IWtwus0Ua0-ZWtxiI", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 464.7289444009635, + "y": 484.4696558316466, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 207.47916194780538, + "height": 5.231236758842954, + "seed": 1324070824, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "W4Y-NK4ifgtz8tLpebNmP" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": { + "elementId": "ivE8803kNip-QGmVRPTJT", + "gap": 14.62055831857424, + "focus": 0.16397172913155103 + }, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -207.47916194780538, + -5.231236758842954 + ] + ] + }, + { + "type": "text", + "version": 20, + "versionNonce": 1250479784, + "isDeleted": false, + "id": "W4Y-NK4ifgtz8tLpebNmP", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 289.2253863762795, + "y": 464.35403745222516, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 143.5279541015625, + "height": 35, + "seed": 217584296, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240665, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "REST API", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ZCy2IWtwus0Ua0-ZWtxiI", + "originalText": "REST API", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "arrow", + "version": 559, + "versionNonce": 439275480, + "isDeleted": false, + "id": "5n_B9CJuQSbh_9oqVzuI6", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 202.52949146560832, + "y": 440.31985181770045, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 272.8426527029128, + "height": 314.68993033808175, + "seed": 183894184, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "_OEHTl2PZTnuWn-1mAEiT" + } + ], + "updated": 1702808240665, + "link": null, + "locked": false, + "startBinding": { + "elementId": "OjLHq6b5pr-RJLnhmhb9K", + "focus": -0.13753799019063503, + "gap": 10.35604214156509 + }, + "endBinding": { + "elementId": "kQEs74aFmFnjuSm-p72OE", + "focus": -0.08628183567880451, + "gap": 10.620705807546301 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -0.7521460748805566, + -314.68993033808175 + ], + [ + 272.09050662803224, + -314.6167125785801 + ] + ] + }, + { + "type": "text", + "version": 11, + "versionNonce": 13154728, + "isDeleted": false, + "id": "_OEHTl2PZTnuWn-1mAEiT", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 149.23537609141135, + "y": 108.1299214796187, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 105.08393859863281, + "height": 35, + "seed": 282316200, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "webhook", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "5n_B9CJuQSbh_9oqVzuI6", + "originalText": "webhook", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "arrow", + "version": 76, + "versionNonce": 1484199128, + "isDeleted": false, + "id": "3CctNqXoAGgfLtMVAW8GE", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 50, + "angle": 0, + "x": 751.8692015743843, + "y": 120.68221795976856, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 57.941872405622235, + "height": 0.32615183778005985, + "seed": 961931432, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "VprgBUfB4-wBA0Fq7V3Z1", + "focus": 0.03598892594670091, + "gap": 3.2757841338804496 + }, + "endBinding": { + "elementId": "R0smI5sVq2H9Cbtg0AVI7", + "focus": 0.12703530284919762, + "gap": 11.461144149285666 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 57.941872405622235, + 0.32615183778005985 + ] + ] + }, + { + "type": "arrow", + "version": 69, + "versionNonce": 1574126760, + "isDeleted": false, + "id": "vEz4-_ilsOBuVZj_DPvkJ", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 1056.8825301019726, + "y": 117.2470877763239, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 38.64800871774992, + "height": 0.02555897409504837, + "seed": 773374168, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "t6kcifZDQhbV_nWUqOl38", + "focus": -0.048809902203905846, + "gap": 9.161574238951289 + }, + "endBinding": { + "elementId": "nV1Lv6Z9RwU1kyPtg_KkZ", + "focus": 0.010158572367500326, + "gap": 4.6205238772413395 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 38.64800871774992, + -0.02555897409504837 + ] + ] + }, + { + "type": "arrow", + "version": 72, + "versionNonce": 258914776, + "isDeleted": false, + "id": "dySicUMsQbgCIoOX-MYqw", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 1174.9138724729864, + "y": 118.20696924789414, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 41.74916424128469, + "height": 0, + "seed": 1458113960, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "nV1Lv6Z9RwU1kyPtg_KkZ", + "focus": 0.021195575596268702, + "gap": 10.301657411065662 + }, + "endBinding": { + "elementId": "U2pwmC5ui2QgIyOhovNXp", + "focus": -0.04394364760382134, + "gap": 3.847791388797873 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 41.74916424128469, + 0 + ] + ] + }, + { + "type": "arrow", + "version": 128, + "versionNonce": 1867804584, + "isDeleted": false, + "id": "_pz_3_mcUDfEsFbLSG4mL", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 614.7406771174399, + "y": 123.46927802546713, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 62.62800619094287, + "height": 0.5083395958907317, + "seed": 706689704, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "2MGNA2z3GcTn0mTa2zdNs", + "focus": 0.09187991420798045, + "gap": 10.815644694940147 + }, + "endBinding": { + "elementId": "VprgBUfB4-wBA0Fq7V3Z1", + "focus": -0.10250470244167695, + "gap": 6.763581767164112 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 62.62800619094287, + -0.5083395958907317 + ] + ] + }, + { + "type": "rectangle", + "version": 2278, + "versionNonce": 841596632, + "isDeleted": false, + "id": "KqWZSlwJgeKzNny0t4qUD", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1194.7514152558729, + "y": 686.0049911651249, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1783918296, + "groupIds": [ + "HYQcTB0OWr_NEwBKtm5Tk", + "uOZ6hlv_NPeAeKJg2zhWj", + "8FmkxyonSTe_DjOlJamzM", + "PDhSp71YzDH5c2joqdU4n" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1259, + "versionNonce": 762854056, + "isDeleted": false, + "id": "WUsz_PI3dfbenaihAB_0o", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1227.6406201017357, + "y": 712.4366267884079, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 21.841043343648586, + "height": 21.841043343648586, + "seed": 1888539608, + "groupIds": [ + "9Q6YIkMcBoWOAJWpu29ei", + "8FmkxyonSTe_DjOlJamzM", + "PDhSp71YzDH5c2joqdU4n" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1358, + "versionNonce": 826024920, + "isDeleted": false, + "id": "2TEQ2j6zp5yVPKfbXd8TC", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1230.6126579806532, + "y": 715.4209926302692, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 15.995025530159795, + "height": 15.995025530159795, + "seed": 469276888, + "groupIds": [ + "9Q6YIkMcBoWOAJWpu29ei", + "8FmkxyonSTe_DjOlJamzM", + "PDhSp71YzDH5c2joqdU4n" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1454, + "versionNonce": 720020904, + "isDeleted": false, + "id": "vSRc_g7C4ffbUoehc2YVE", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1243.1151541471345, + "y": 733.2771913308634, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 9.151218017876092, + "height": 10.091076767857256, + "seed": 1881128408, + "groupIds": [ + "9Q6YIkMcBoWOAJWpu29ei", + "8FmkxyonSTe_DjOlJamzM", + "PDhSp71YzDH5c2joqdU4n" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 6.168060525924741, + 7.91444045501081 + ], + [ + 8.989033712179662, + 8.010284255302183 + ], + [ + 9.151218017876092, + 5.512226866678265 + ], + [ + 3.2231092420771543, + -2.080792512555073 + ] + ] + }, + { + "type": "line", + "version": 3427, + "versionNonce": 1253697752, + "isDeleted": false, + "id": "NTWwJHNmrg3KWEr4qfdP_", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1251.9872447704706, + "y": 717.6261890503365, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 51.20925119386821, + "height": 31.346195428564556, + "seed": 1578779352, + "groupIds": [ + "9Q6YIkMcBoWOAJWpu29ei", + "8FmkxyonSTe_DjOlJamzM", + "PDhSp71YzDH5c2joqdU4n" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.7019871718007114, + -4.829355828674696 + ], + [ + -1.6224572311732235, + -8.49331278461991 + ], + [ + -6.126805998801945, + -9.755950990552602 + ], + [ + -6.636812422697123, + -10.606384505992917 + ], + [ + -7.557495501631415, + -14.327812919294981 + ], + [ + -11.807523972968628, + -16.07173954496999 + ], + [ + -15.685983674796862, + -13.618555037195279 + ], + [ + -16.10752432751427, + -14.007414596177838 + ], + [ + -22.066170177703448, + -20.331419411454842 + ], + [ + -30.802290387121715, + -23.13419750802699 + ], + [ + -39.029469270454406, + -19.57959569240311 + ], + [ + -42.9254717597682, + -10.684831709042832 + ], + [ + -43.53966981076644, + -9.209356170530938 + ], + [ + -49.482289071530886, + -5.437655712898088 + ], + [ + -50.507264022067496, + 2.3029843499115477 + ], + [ + -45.59746384395778, + 7.662372111781902 + ], + [ + -39.77364684615847, + 8.138198233547083 + ], + [ + -32.60818252258176, + 8.211997920537568 + ], + [ + -27.80227478104559, + 8.104207523821323 + ] + ] + }, + { + "type": "text", + "version": 2604, + "versionNonce": 1154986152, + "isDeleted": false, + "id": "hetmGuecDNyTMkW_9cvUv", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1170.9819914383518, + "y": 754.9502816922204, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 111.43991088867188, + "height": 24, + "seed": 343680984, + "groupIds": [ + "PDhSp71YzDH5c2joqdU4n" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "CloudWatch", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "CloudWatch", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "line", + "version": 1308, + "versionNonce": 1513557464, + "isDeleted": false, + "id": "QrT7n6lWdJ4eS-ANxEQ-B", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1241.4783633783245, + "y": 418.73981610422874, + "strokeColor": "#000000", + "backgroundColor": "#868e96", + "width": 68.65265455930219, + "height": 47.990271018315184, + "seed": 1025758168, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.105427357601002e-15, + 23.995135509157592 + ], + [ + 41.1915927355813, + 23.995135509157585 + ], + [ + 41.19159273558131, + 35.99270326373639 + ], + [ + 68.65265455930219, + 11.997567754578782 + ], + [ + 41.19159273558131, + -11.997567754578792 + ], + [ + 41.19159273558131, + 3.552713678800501e-15 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 1820, + "versionNonce": 1391156136, + "isDeleted": false, + "id": "tq1zS2x2Ef1SqMhpqBRrA", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.144564265631301, + "x": 1076.8320877062424, + "y": 418.1407372521284, + "strokeColor": "#000000", + "backgroundColor": "#868e96", + "width": 68.65265455930219, + "height": 47.990271018315184, + "seed": 98967976, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.105427357601002e-15, + 23.995135509157592 + ], + [ + 41.1915927355813, + 23.995135509157585 + ], + [ + 41.19159273558131, + 35.99270326373639 + ], + [ + 68.65265455930219, + 11.997567754578782 + ], + [ + 41.19159273558131, + -11.997567754578792 + ], + [ + 41.19159273558131, + 3.552713678800501e-15 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "arrow", + "version": 102, + "versionNonce": 684167896, + "isDeleted": false, + "id": "6iO3ZeCIQ2iX8l7aF1W0f", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 651.9268236746884, + "y": 982.3944152452901, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 89.2249124038334, + "height": 1.4693197109402263, + "seed": 603624872, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "9A9ymB7KBKZlxIU_b8X-p", + "focus": 0.13990009177428286, + "gap": 10.571673323408334 + }, + "endBinding": { + "elementId": "ckHQnZo6y_sITM7X4uOh2", + "focus": -0.014790824769439796, + "gap": 3.711619276026397 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 89.2249124038334, + -1.4693197109402263 + ] + ] + }, + { + "type": "arrow", + "version": 77, + "versionNonce": 1464968872, + "isDeleted": false, + "id": "sB1bSldBW6W9Ael4sGSCI", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 1089.777791441694, + "y": 982.9745758178502, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 76.48029808705132, + "height": 0.9963627224401534, + "seed": 1676520664, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "XDRmZYk2bUUh_OuCE_imI", + "focus": 0.13348686245776895, + "gap": 11.136759239587377 + }, + "endBinding": { + "elementId": "bseMzya9y50b8CCr1bgn-", + "focus": -0.21267679960554894, + "gap": 3.362070476777717 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 76.48029808705132, + 0.9963627224401534 + ] + ] + }, + { + "type": "arrow", + "version": 730, + "versionNonce": 1023375320, + "isDeleted": false, + "id": "CY9kqXcqCclWzV_SdZgnZ", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 838.3727746345963, + "y": 412.40991473084773, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 195.64654090952888, + "height": 3.7671178470273503, + "seed": 1092851928, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "69FR0y28xceWbpfvy30cc" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "W6naSg5WGUxkEWtp9fIKN", + "focus": -0.5775365778920502, + "gap": 9.574374965051788 + }, + "endBinding": { + "elementId": "0-WIPIwbxU5oirOXK2PXz", + "focus": -0.04557499341333021, + "gap": 19.05249091865926 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 195.64654090952888, + 3.7671178470273503 + ] + ] + }, + { + "type": "text", + "version": 17, + "versionNonce": 783716776, + "isDeleted": false, + "id": "69FR0y28xceWbpfvy30cc", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 868.7208357813679, + "y": 397.2199071816049, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 91.22396850585938, + "height": 35, + "seed": 1536535768, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "create", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "CY9kqXcqCclWzV_SdZgnZ", + "originalText": "create", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "arrow", + "version": 470, + "versionNonce": 720551128, + "isDeleted": false, + "id": "B9LuEtI5fz0cIw_reMJMU", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 846.5770018617776, + "y": 154.31609540664607, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 22.519058745783468, + "height": 218.6007200847328, + "seed": 496305112, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "9y31e3vEHEVxUCCei9ZTk", + "focus": -0.07528363258071558, + "gap": 3.3653425579450698 + }, + "endBinding": { + "elementId": "3_YliClQBodWJoWEXxaHg", + "focus": 0.14150865836763216, + "gap": 5.926481630430601 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 2.9575577014204555, + 217.72417313271268 + ], + [ + -19.561501044363013, + 218.6007200847328 + ] + ] + }, + { + "type": "arrow", + "version": 484, + "versionNonce": 1078336680, + "isDeleted": false, + "id": "A0Q4ehpvRidAU5HGJoEUB", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 825.6470785973545, + "y": 497.43230391159267, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 197.7212455657492, + "height": 3.1512646421606405, + "seed": 1762161320, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "wXOhaoZwO0Ma2PDsEHxue" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "vv1ewWvR1lmII3MPO4kSQ", + "gap": 12.59079124879014, + "focus": 0.029529635933343828 + }, + "endBinding": { + "elementId": "0-WIPIwbxU5oirOXK2PXz", + "gap": 29.703482299680786, + "focus": -0.4649249881772308 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 197.7212455657492, + -3.1512646421606405 + ] + ] + }, + { + "type": "text", + "version": 13, + "versionNonce": 1681220056, + "isDeleted": false, + "id": "wXOhaoZwO0Ma2PDsEHxue", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 859.5477328133345, + "y": 478.35667159051235, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 129.91993713378906, + "height": 35, + "seed": 1983913688, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "terminate", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "A0Q4ehpvRidAU5HGJoEUB", + "originalText": "terminate", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "arrow", + "version": 563, + "versionNonce": 766265256, + "isDeleted": false, + "id": "9ABOs5-WXUCCZ-D8t85bL", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 807.8323653638516, + "y": 717.1122326794728, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 233.50832436225494, + "height": 205.10887874930518, + "seed": 862970328, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "type": "text", + "id": "RJW7-L_4OhaxKIoboEq8z" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "n9qmPQ5oyMHvQSgbGrMne", + "gap": 10.457257931373135, + "focus": 0.5331845279876658 + }, + "endBinding": { + "elementId": "0-WIPIwbxU5oirOXK2PXz", + "gap": 11.731116736678018, + "focus": 0.09110333045867611 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 233.50832436225494, + -205.10887874930518 + ] + ] + }, + { + "type": "text", + "version": 10, + "versionNonce": 131819224, + "isDeleted": false, + "id": "RJW7-L_4OhaxKIoboEq8z", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 878.9745432920495, + "y": 597.0577933048202, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 91.22396850585938, + "height": 35, + "seed": 615826648, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "create", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "9ABOs5-WXUCCZ-D8t85bL", + "originalText": "create", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "arrow", + "version": 105, + "versionNonce": 51712680, + "isDeleted": false, + "id": "ztTiOSNqcEkLEIthcdd1V", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 620.1693384202035, + "y": 495.6712253332772, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 117.94916683873771, + "height": 2.1188473084802126, + "seed": 1607364568, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "JPqW94G_1U4n_Rtp1AVB3", + "focus": -0.020750296933416363, + "gap": 9.001944141892238 + }, + "endBinding": { + "elementId": "vv1ewWvR1lmII3MPO4kSQ", + "focus": 0.13410223290661427, + "gap": 10.476629724665997 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 117.94916683873771, + -2.1188473084802126 + ] + ] + }, + { + "type": "arrow", + "version": 66, + "versionNonce": 846777304, + "isDeleted": false, + "id": "h_B89cGbWb6iNZ006NPoL", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 634.9129842750458, + "y": 720.004184118631, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 87.64208301565316, + "height": 0.5170996407600796, + "seed": 1977029032, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "uUv0KoFONcaKfwZdcWlGA", + "focus": 0.011219565185519488, + "gap": 9.478784417754696 + }, + "endBinding": { + "elementId": "n9qmPQ5oyMHvQSgbGrMne", + "focus": 0.0961574415945354, + "gap": 10.358887776822542 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 87.64208301565316, + -0.5170996407600796 + ] + ] + }, + { + "type": "rectangle", + "version": 1039, + "versionNonce": 1730969000, + "isDeleted": false, + "id": "LyeVp7KMhpgKr0URszD88", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1464.4036723266968, + "y": 14.381353682960707, + "strokeColor": "#d94576", + "backgroundColor": "transparent", + "width": 1157.2084417081958, + "height": 443.6494596044594, + "seed": 776971944, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "cUPaaf9O5p9ArRVfoz6gA", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2436, + "versionNonce": 824594681, + "isDeleted": false, + "id": "mxcHW5eh9iYvoHOZYqgWO", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -1414.5881719269546, + "y": 23.83265849601935, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 40.199981689453125, + "height": 25, + "seed": 1978962344, + "groupIds": [ + "3fjhGOH4fjrNDUT8euuwu" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "AWS", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "AWS", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "rectangle", + "version": 774, + "versionNonce": 1260292264, + "isDeleted": false, + "id": "zUYX9sScR_1l8bEgwhODs", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1463.303310971538, + "y": 15.07081663501117, + "strokeColor": "#d94576", + "backgroundColor": "transparent", + "width": 39.6243416500605, + "height": 42.52368372201621, + "seed": 1875123368, + "groupIds": [ + "3F0yWccZYcDQ3NTQaIESP", + "2M0FvfGH08bleIVbmkCHQ", + "3fjhGOH4fjrNDUT8euuwu" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 376, + "versionNonce": 1651095000, + "isDeleted": false, + "id": "M1eDHAgmbLaL6hEPrqac1", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1457.5536401465076, + "y": 22.27015849601935, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 28.125, + "height": 28.125, + "seed": 1030375336, + "groupIds": [ + "9XFbTG1ULbiVY5JvQMAnk", + "2M0FvfGH08bleIVbmkCHQ", + "3fjhGOH4fjrNDUT8euuwu" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 371, + "versionNonce": 446116776, + "isDeleted": false, + "id": "o6G5meIX95a1t1o2XCOSD", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1453.8036401465076, + "y": 32.02015849601935, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.125, + "height": 8.125, + "seed": 1796412072, + "groupIds": [ + "9XFbTG1ULbiVY5JvQMAnk", + "2M0FvfGH08bleIVbmkCHQ", + "3fjhGOH4fjrNDUT8euuwu" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 365, + "versionNonce": 1684355800, + "isDeleted": false, + "id": "V7hFMeuURQ3IZRGY8gAjB", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1443.1786401465076, + "y": 38.52015849601935, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.125, + "height": 8.125, + "seed": 527072680, + "groupIds": [ + "9XFbTG1ULbiVY5JvQMAnk", + "2M0FvfGH08bleIVbmkCHQ", + "3fjhGOH4fjrNDUT8euuwu" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 651, + "versionNonce": 1807908520, + "isDeleted": false, + "id": "RZR8QMW6YQa_hGs2u1lXr", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1441.6786401465076, + "y": 33.89515849601935, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.874999999999981, + "height": 7.874999999999979, + "seed": 1268549800, + "groupIds": [ + "9XFbTG1ULbiVY5JvQMAnk", + "2M0FvfGH08bleIVbmkCHQ", + "3fjhGOH4fjrNDUT8euuwu" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 3.374999999999991, + -7.874999999999979 + ], + [ + 6.874999999999981, + 0 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "rectangle", + "version": 1947, + "versionNonce": 111681496, + "isDeleted": false, + "id": "lM-MbggFi2bltfg5ZKqu9", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -623.8471206672966, + "y": 223.53567996800217, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1532310440, + "groupIds": [ + "li31b0JAlGEOMweU5ureD", + "y7LI2rJI8Rj5-uisga4jS", + "P-wHA79fIrW66omvQ2vSa" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1310, + "versionNonce": 793536936, + "isDeleted": false, + "id": "Ux0100oEgMVNINMOZZFH-", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -602.060991439464, + "y": 244.74188203412797, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 21.136985907710482, + "height": 21.58982944276917, + "seed": 1690336936, + "groupIds": [ + "hRcTEX7n-FVKqfuCVFoHm", + "y7LI2rJI8Rj5-uisga4jS", + "P-wHA79fIrW66omvQ2vSa" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1635, + "versionNonce": 155608280, + "isDeleted": false, + "id": "Je3NkXdbc3vCtJgNX5aSp", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.726840450960482, + "x": -590.9811065294234, + "y": 262.74403031823414, + "strokeColor": "#000", + "backgroundColor": "transparent", + "width": 21.298113442520286, + "height": 21.325685740313624, + "seed": 1485466024, + "groupIds": [ + "kRZSEdQ-ADKp1ZkBMwTLA", + "hRcTEX7n-FVKqfuCVFoHm", + "y7LI2rJI8Rj5-uisga4jS", + "P-wHA79fIrW66omvQ2vSa" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.05533508667380005, + -8.330350296057105 + ], + [ + -21.16993868276674, + -8.49388689455444 + ], + [ + -21.242778355846482, + 12.60784310791851 + ], + [ + -12.973972126229569, + 12.831798845759185 + ] + ] + }, + { + "type": "line", + "version": 1649, + "versionNonce": 1616966824, + "isDeleted": false, + "id": "D6bobR_SJx_tW02DaIVLT", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5503909961083693, + "x": -572.4516641570892, + "y": 243.97388426232243, + "strokeColor": "#000", + "backgroundColor": "transparent", + "width": 21.298113442520286, + "height": 21.325685740313624, + "seed": 836695208, + "groupIds": [ + "-XY4wKjJs3c1JL2e1a8EO", + "hRcTEX7n-FVKqfuCVFoHm", + "y7LI2rJI8Rj5-uisga4jS", + "P-wHA79fIrW66omvQ2vSa" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.05533508667380005, + -8.330350296057105 + ], + [ + -21.16993868276674, + -8.49388689455444 + ], + [ + -21.242778355846482, + 12.60784310791851 + ], + [ + -12.973972126229569, + 12.831798845759185 + ] + ] + }, + { + "type": "rectangle", + "version": 3574, + "versionNonce": 164891096, + "isDeleted": false, + "id": "60lIX2wtAAtAipl_RV8hj", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1199.2279715472614, + "y": -105.29958058829868, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 644489128, + "groupIds": [ + "d5hlmhYc20DqpG6_uEzyp", + "P1oNr3qlDbERExGVlID3Q", + "atXtxoNG4YchyoIHLwo2f", + "OFUM2i6lmQgH_RPibbYrr", + "rhYTT2ZdeqfKkBHQW-il8" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "MebWehEWzdFtf6cajcDfZ", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1469, + "versionNonce": 883695528, + "isDeleted": false, + "id": "PO-rP7U2f18IlVGlCI2rM", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1192.938646748943, + "y": -98.97280092452579, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 51.88250276832002, + "height": 51.88250276832002, + "seed": 1448602280, + "groupIds": [ + "9oWNpJydM8FOHuFwpaSQw", + "rhYTT2ZdeqfKkBHQW-il8" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "MebWehEWzdFtf6cajcDfZ", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 5087, + "versionNonce": 1399131864, + "isDeleted": false, + "id": "H4hDSTal3M904VyBeBiRl", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1177.1908828182568, + "y": -88.56475031496743, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 28.10264153823924, + "height": 32.45750960039449, + "seed": 2085901736, + "groupIds": [ + "9oWNpJydM8FOHuFwpaSQw", + "rhYTT2ZdeqfKkBHQW-il8" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.522383435627326, + 0.8876695614221044 + ], + [ + 4.222250533550099, + 2.710891079770457 + ], + [ + 6.53876438289814, + 1.9494891881139838 + ], + [ + 13.00273268947289, + 2.0374391115495714 + ], + [ + 15.018859724261578, + 2.2364052653721083 + ], + [ + 16.578273739956423, + 0.9941438562971401 + ], + [ + 18.744233429245106, + -0.5092823311506232 + ], + [ + 19.3382730064762, + 1.5588921397895759 + ], + [ + 19.283438583962543, + 3.566556278350808 + ], + [ + 21.26661686487244, + 5.46749782452002 + ], + [ + 22.153106695509578, + 10.909367329014938 + ], + [ + 21.45853734367018, + 16.608727547781946 + ], + [ + 19.438802781084537, + 18.8230883820351 + ], + [ + 16.687942584983702, + 20.009258415382803 + ], + [ + 13.71774469882833, + 20.664602961087855 + ], + [ + 14.50370475485716, + 21.40308436092641 + ], + [ + 15.390194585494283, + 23.040424434305827 + ], + [ + 15.572975993873055, + 28.176226896819482 + ], + [ + 15.536419712197318, + 31.28569415677526 + ], + [ + 14.567678247789736, + 31.823854903738514 + ], + [ + 7.240428539404906, + 31.948227269243866 + ], + [ + 6.324236729906197, + 31.05132655929166 + ], + [ + 6.068342758175913, + 27.392989048505843 + ], + [ + 4.377614730672068, + 27.862931757494 + ], + [ + 1.5810591824765403, + 28.041957551394276 + ], + [ + -1.0327149573401755, + 26.542616527479623 + ], + [ + -2.659469491911409, + 23.92436429168835 + ], + [ + -4.240528674387946, + 22.313132146586064 + ], + [ + -5.949534842729662, + 21.179302118551103 + ], + [ + -3.628210956319009, + 21.40308436092641 + ], + [ + -1.9831782809098755, + 22.671183734386556 + ], + [ + -0.11880791544621871, + 24.43906344915162 + ], + [ + 2.147681548450816, + 25.543055844869823 + ], + [ + 4.660925913659192, + 25.22976070554441 + ], + [ + 5.9038394906349865, + 24.252578247172192 + ], + [ + 6.022647406081191, + 22.71594018286161 + ], + [ + 6.689799546663803, + 21.380706136688904 + ], + [ + 7.558011236463052, + 20.776494082275484 + ], + [ + 4.277084956063728, + 19.93358096932851 + ], + [ + 1.1423838023674477, + 18.89984919335192 + ], + [ + -0.4569535209469784, + 16.571430507386058 + ], + [ + -1.6541717458280658, + 10.963038997107194 + ], + [ + -0.7037084222583516, + 5.6861115380996985 + ], + [ + 0.6671521405825978, + 4.240069736001822 + ], + [ + -0.11880791544621871, + 2.2772861946741387 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "rectangle", + "version": 1336, + "versionNonce": 1280961192, + "isDeleted": false, + "id": "CghUVjBmEFxGr179I3n5J", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -758.07861552822, + "y": 119.88692960021291, + "strokeColor": "#2b8a3e", + "backgroundColor": "transparent", + "width": 340.4929295645432, + "height": 284.90360380716174, + "seed": 495673512, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "cUPaaf9O5p9ArRVfoz6gA", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 2516, + "versionNonce": 400430871, + "isDeleted": false, + "id": "OCZ8RKQ44a26RZW6ydFiH", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -708.7037727682573, + "y": 128.61748915149502, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 36.439971923828125, + "height": 25, + "seed": 967379880, + "groupIds": [ + "kKAhDTQ-Z_1aXHBDfDa9b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "VPC", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "VPC", + "lineHeight": 1.25, + "baseline": 18 + }, + { + "type": "rectangle", + "version": 865, + "versionNonce": 1645630888, + "isDeleted": false, + "id": "Wu7sSnSXSiWpf3l0bE1jn", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -757.4189118128406, + "y": 119.85564729048684, + "strokeColor": "#2b8a3e", + "backgroundColor": "transparent", + "width": 39.6243416500605, + "height": 42.52368372201621, + "seed": 2061063848, + "groupIds": [ + "CoUwUkb_jUYUbQn5QV4WC", + "kKAhDTQ-Z_1aXHBDfDa9b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 3970, + "versionNonce": 828455128, + "isDeleted": false, + "id": "K7LNLxiwAM1IRD8n17x3s", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -724.5112568262261, + "y": 149.514635211197, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 32.27574323253867, + "height": 18.361713520282862, + "seed": 1707622824, + "groupIds": [ + "hfgzfaVDIGY9rs2unObdG", + "CoUwUkb_jUYUbQn5QV4WC", + "kKAhDTQ-Z_1aXHBDfDa9b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 3.549984432244912, + -3.8949537333214295 + ], + [ + 2.3636841312957984, + -8.495303540186455 + ], + [ + -2.7289433979513547, + -10.111388238124647 + ], + [ + -3.027690717076837, + -10.609548106174614 + ], + [ + -3.567000789869894, + -12.789455475380407 + ], + [ + -6.056547102486405, + -13.810998302611608 + ], + [ + -8.328438953196809, + -12.373992295078466 + ], + [ + -8.57536552902286, + -12.601775211762344 + ], + [ + -12.065771512081795, + -16.306198129166546 + ], + [ + -17.183143313379162, + -17.9479861601084 + ], + [ + -22.002391699683074, + -15.86580108709353 + ], + [ + -24.284559618469785, + -10.65550025600254 + ], + [ + -24.644339441920692, + -9.79120847277541 + ], + [ + -28.1253575027867, + -7.581853163765089 + ], + [ + -28.72575880029376, + -3.0476054391618987 + ], + [ + -25.849736907374307, + 0.09177212746608632 + ], + [ + -22.43830984753089, + 0.3704975936309154 + ], + [ + -18.24098378130509, + 0.41372736017446243 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "rectangle", + "version": 959, + "versionNonce": 2064474280, + "isDeleted": false, + "id": "tRk__hU6Y5IHHm-Hft678", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -741.9936653301397, + "y": 140.7764682343771, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 6.723014307274803, + "height": 6.1627631150019475, + "seed": 161598632, + "groupIds": [ + "-9SB6OVu5YlVrmR6nQWD5", + "hfgzfaVDIGY9rs2unObdG", + "CoUwUkb_jUYUbQn5QV4WC", + "kKAhDTQ-Z_1aXHBDfDa9b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1103, + "versionNonce": 259284440, + "isDeleted": false, + "id": "Fj6EY783vdHKqJngY2JK-", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -741.7961157359264, + "y": 140.69346805773517, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 3.735007948486001, + "height": 3.735007948486001, + "seed": 806483880, + "groupIds": [ + "-9SB6OVu5YlVrmR6nQWD5", + "hfgzfaVDIGY9rs2unObdG", + "CoUwUkb_jUYUbQn5QV4WC", + "kKAhDTQ-Z_1aXHBDfDa9b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.1660003532660483, + -0.8300017663302128 + ], + [ + 0.5810012364311606, + -2.0750044158255605 + ], + [ + 1.4940031793944009, + -2.9880063587888444 + ], + [ + 2.407005122357648, + -3.652007771852979 + ], + [ + 3.735007948486001, + -3.7350079484860075 + ] + ] + }, + { + "type": "line", + "version": 1182, + "versionNonce": 384502696, + "isDeleted": false, + "id": "Ohe4w4CUkJLo_fzmVsNgd", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -735.4781514644478, + "y": 140.71919352557603, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 3.735007948486001, + "height": 3.735007948486001, + "seed": 222610088, + "groupIds": [ + "-9SB6OVu5YlVrmR6nQWD5", + "hfgzfaVDIGY9rs2unObdG", + "CoUwUkb_jUYUbQn5QV4WC", + "kKAhDTQ-Z_1aXHBDfDa9b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -0.16600035326605678, + -0.8300017663301986 + ], + [ + -0.5810012364311561, + -2.0750044158255605 + ], + [ + -1.494003179394383, + -2.9880063587888444 + ], + [ + -2.407005122357667, + -3.652007771852979 + ], + [ + -3.7350079484860075, + -3.7350079484860075 + ] + ] + }, + { + "type": "arrow", + "version": 3361, + "versionNonce": 1775952600, + "isDeleted": false, + "id": "cUPaaf9O5p9ArRVfoz6gA", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -990.1156922138289, + "y": 277.01133076025866, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 225.51440740660746, + "height": 1.307271401920616, + "seed": 1877355944, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "O_IqjSYNMnRbz7El-umgW", + "focus": 0.11807151745670481, + "gap": 1.16494150791425 + }, + "endBinding": { + "elementId": "CghUVjBmEFxGr179I3n5J", + "focus": -0.08603414308172914, + "gap": 6.522669279001406 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + 225.51440740660746, + -1.307271401920616 + ] + ] + }, + { + "type": "rectangle", + "version": 1384, + "versionNonce": 1608210088, + "isDeleted": false, + "id": "O_IqjSYNMnRbz7El-umgW", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1375.1306210844218, + "y": 119.04657996627105, + "strokeColor": "#d94576", + "backgroundColor": "transparent", + "width": 383.8499873626786, + "height": 284.3336918168821, + "seed": 1898068136, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "cUPaaf9O5p9ArRVfoz6gA", + "type": "arrow" + }, + { + "id": "MebWehEWzdFtf6cajcDfZ", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 507, + "versionNonce": 1845742041, + "isDeleted": false, + "id": "NtUuRgisoTTVqG2HfRVWH", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -1355.9150135297377, + "y": 358.3631133688736, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 337.7638854980469, + "height": 36, + "seed": 614785960, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Serverless Control Plane", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Serverless Control Plane", + "lineHeight": 1.2857142857142858, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 1801, + "versionNonce": 1519010216, + "isDeleted": false, + "id": "T8iumlJy-owHD_ZBNxGl3", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1263.33868482198, + "y": 256.46777895589133, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 64.46115236495699, + "height": 64.39942473426015, + "seed": 1218064040, + "groupIds": [ + "aNeWbtsNmj9Shi3Wrk3oq", + "SGuABbxfVYSCRYlTZnBSJ", + "zxGjTX0gm2tUqkORRbFUd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 964, + "versionNonce": 460459224, + "isDeleted": false, + "id": "bcjHfWN2HxaZFKyIvKxNn", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1238.3474772715329, + "y": 283.2052447409905, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 19.307143399999998, + "height": 26.897, + "seed": 1974344104, + "groupIds": [ + "Bg-nWP6JU2OXACNwU7Rg2", + "SGuABbxfVYSCRYlTZnBSJ", + "zxGjTX0gm2tUqkORRbFUd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -12.730345799999998, + 25.466 + ], + [ + -0.5178580999999962, + 26.897 + ], + [ + 6.576797599999999, + 13.180999999999997 + ], + [ + 0.8992804999999997, + 0.5640000000000001 + ] + ] + }, + { + "type": "line", + "version": 964, + "versionNonce": 371444904, + "isDeleted": false, + "id": "fCbLW61Jg2a4PVVbk2cIc", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1213.8607570715328, + "y": 299.10224474099044, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 34.863799400000005, + "height": 44, + "seed": 1326228648, + "groupIds": [ + "Bg-nWP6JU2OXACNwU7Rg2", + "SGuABbxfVYSCRYlTZnBSJ", + "zxGjTX0gm2tUqkORRbFUd" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -14.960123300000012, + -32.42 + ], + [ + -29.1743317, + -33 + ], + [ + -30.178179700000005, + -23.001 + ], + [ + -22.897294200000005, + -22 + ], + [ + -7.866463500000002, + 10.421999999999997 + ], + [ + 3.689738799999993, + 11 + ], + [ + 4.685619699999997, + 1.0000000000000002 + ], + [ + 3.6897387999999935, + 0 + ] + ] + }, + { + "type": "rectangle", + "version": 1289, + "versionNonce": 675983832, + "isDeleted": false, + "id": "u9dctUub-9xoUE-4i2mBW", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1149.0340908197434, + "y": 150.93672713051973, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 845270952, + "groupIds": [ + "0Flc726FbxzCwcZbm_RHk", + "pZtmi77xaFG7WtcLOTrMO", + "zMAKusZNbVCZxvIWyZVCV", + "SLbk-WQ4OPj6Nk63Zk3xR" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "u9dctUub-9xoUE-4i2mBW", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1074, + "versionNonce": 1549006760, + "isDeleted": false, + "id": "4snnvDA89f_34tGZbYxNE", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1135.4212356420844, + "y": 162.0038231560356, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 39.10563151041674, + "height": 10.753995455228363, + "seed": 1742314152, + "groupIds": [ + "zMAKusZNbVCZxvIWyZVCV", + "SLbk-WQ4OPj6Nk63Zk3xR" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1692, + "versionNonce": 1019655896, + "isDeleted": false, + "id": "IE3pCRSR-oSv3lWMnhwCw", + "fillStyle": "hachure", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1135.063319225818, + "y": 167.88229120491354, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 38.295773237179446, + "height": 40.48662140675077, + "seed": 1377830312, + "groupIds": [ + "zMAKusZNbVCZxvIWyZVCV", + "SLbk-WQ4OPj6Nk63Zk3xR" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 3.8452774439103905, + 32.14685684595355 + ], + [ + 6.768312737880933, + 37.98883103590748 + ], + [ + 20.34867663261207, + 40.48662140675077 + ], + [ + 32.537268066406114, + 38.400380608974274 + ], + [ + 35.36686823918285, + 31.944173177083314 + ], + [ + 38.295773237179446, + 0.09767190004004078 + ] + ] + }, + { + "type": "ellipse", + "version": 1084, + "versionNonce": 1632027304, + "isDeleted": false, + "id": "b_HHLmW_mL0QAHeIHKzcF", + "fillStyle": "solid", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1118.2930311398804, + "y": 178.14479038328653, + "strokeColor": "#000000", + "backgroundColor": "#000", + "width": 4.69818115234375, + "height": 4.69818115234375, + "seed": 509677736, + "groupIds": [ + "zMAKusZNbVCZxvIWyZVCV", + "SLbk-WQ4OPj6Nk63Zk3xR" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1770, + "versionNonce": 1299848152, + "isDeleted": false, + "id": "VyCWCQPha0ZkSpTMmk2ET", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1115.8029127316775, + "y": 180.717780800767, + "strokeColor": "#000000", + "backgroundColor": "#000", + "width": 23.24691772460949, + "height": 11.53113708496096, + "seed": 1950923688, + "groupIds": [ + "zMAKusZNbVCZxvIWyZVCV", + "SLbk-WQ4OPj6Nk63Zk3xR" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 7.0229309082030795, + 7.4353179931640625 + ], + [ + 17.00493774414076, + 11.53113708496096 + ], + [ + 22.923687744140693, + 10.143841552734386 + ], + [ + 23.24691772460949, + 5.890612792968767 + ], + [ + 17.962628173828193, + 1.7561248779296932 + ] + ] + }, + { + "type": "rectangle", + "version": 1187, + "versionNonce": 1940401576, + "isDeleted": false, + "id": "b8No1K7Tz6j1dEf3xHoSN", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1149.0340908197434, + "y": 256.3335961583786, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 637732520, + "groupIds": [ + "KlQ6wfD_t5xKDrbumP4uP", + "BcYKfi8G_EDc3T8OgfWfX", + "VR6fKG4kyOuwmS-hltkIo", + "Ilf0IQvcb06WmBPEO1pGu", + "IWRosNEj55VmJ-HuL243g", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "b8No1K7Tz6j1dEf3xHoSN", + "type": "arrow" + } + ], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 885, + "versionNonce": 477683928, + "isDeleted": false, + "id": "BvbUdH1-fly-4AgYezrkr", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1140.8504393517153, + "y": 285.44027066178404, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 1614541224, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 940, + "versionNonce": 748959912, + "isDeleted": false, + "id": "0nVIfaybDj6OcdNmpYyS3", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1099.7926723020958, + "y": 285.3668355683182, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 1512012968, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1557, + "versionNonce": 156698072, + "isDeleted": false, + "id": "rBvk8SsOHDzPGIkWUUn4S", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1123.8692180056726, + "y": 281.7598754072898, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 89761704, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 1631, + "versionNonce": 535225256, + "isDeleted": false, + "id": "ElOhoMg9fbKZoXYFhDdNV", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5707963267948957, + "x": -1117.3077222869344, + "y": 275.83271637420165, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.6587160660160247, + "height": 14.901485256991352, + "seed": 1041658536, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 1661, + "versionNonce": 1630046936, + "isDeleted": false, + "id": "AnXMaOP3ttfHmjInqVKxN", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": -1111.3733183886864, + "y": 282.3515614732252, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 2063719848, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 1748, + "versionNonce": 194784936, + "isDeleted": false, + "id": "-oswUBiFFQE-i7jsmiIDX", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.71238898038469, + "x": -1117.925719814655, + "y": 288.2995753924353, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.6587160660160247, + "height": 14.901485256991352, + "seed": 2101864616, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 1159, + "versionNonce": 780234712, + "isDeleted": false, + "id": "yFTMxNCJ09phr8gMBzxph", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1130.7057636727498, + "y": 289.5139954515518, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 9737128, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 1175, + "versionNonce": 141564328, + "isDeleted": false, + "id": "Oi6xdDvg6I0c6x-RykZiB", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1108.1119150458119, + "y": 289.6368659131892, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 1796464296, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 1151, + "versionNonce": 158708952, + "isDeleted": false, + "id": "v4as2DOOewlA8tq2v57cS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1136.8270453685197, + "y": 285.4840900443034, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.10905784483692, + "seed": 2104609192, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "line", + "version": 1255, + "versionNonce": 965649576, + "isDeleted": false, + "id": "imREQhwV8y4f_EYTFkocc", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": -1137.0807027415315, + "y": 310.17167371645445, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.10905784483692, + "seed": 47862952, + "groupIds": [ + "HDGwDCv02_iYnJntw129N", + "PpbOWmPGPg5SqAuXnBoTz", + "SwpKBe7uSpesdP6MQ_4MW" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "rectangle", + "version": 1465, + "versionNonce": 1738103256, + "isDeleted": false, + "id": "ZLqsR14BwFGafeDu1AfXW", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1263.2737854481868, + "y": 150.5121058527505, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 64.65338134765624, + "height": 64.65338134765624, + "seed": 16351144, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 1938, + "versionNonce": 2091110312, + "isDeleted": false, + "id": "n6yMb70HlDMBeM_z4uiJm", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1238.377285102704, + "y": 170.60820137577667, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 15.16932105348633, + "height": 0, + "seed": 1744521896, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 15.16932105348633, + 0 + ] + ] + }, + { + "type": "line", + "version": 1989, + "versionNonce": 1811963608, + "isDeleted": false, + "id": "Jf2bYWhzZYyIbz_95cBzM", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "dotted", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1239.8491794561457, + "y": 195.38709589427282, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 17.13783740126311, + "height": 0, + "seed": 1116452264, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 17.13783740126311, + 0 + ] + ] + }, + { + "type": "line", + "version": 1835, + "versionNonce": 433822376, + "isDeleted": false, + "id": "RxBtiNJaACMT1pWekyIpS", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1256.6497290644577, + "y": 166.43754080923765, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 16.95504631353927, + "height": 48.41270068259871, + "seed": 1708572840, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 16.95504631353927, + -7.400560664373661 + ], + [ + 16.871549804500688, + 41.01214001822505 + ], + [ + 0.08056087780811456, + 33.450908214315675 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 1783, + "versionNonce": 926860248, + "isDeleted": false, + "id": "PyqqZqXU8mtQl6KnFnt75", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1222.188685385158, + "y": 158.85192935003062, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 16.976775286010504, + "height": 48.27905988118746, + "seed": 562588584, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0.1970252545028261, + 48.27905988118746 + ], + [ + 16.961573619999825, + 40.954321999069336 + ], + [ + 16.976775286010504, + 7.507893438730637 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 1508, + "versionNonce": 1944192424, + "isDeleted": false, + "id": "MB-aaOAYYl9_gy-givo3s", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1235.5077171716432, + "y": 188.98756891272689, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 9.101119485207235, + "height": 12.203935908273408, + "seed": 1875687080, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 9.101119485207235, + -12.203935908273408 + ] + ] + }, + { + "type": "line", + "version": 1626, + "versionNonce": 929597656, + "isDeleted": false, + "id": "zaS1yhgbqdqijMYmTyovu", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": -1227.6992031668362, + "y": 179.11881499428347, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.016669064250991, + "height": 8.41385706862771, + "seed": 625975720, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.00572174417704, + 4.3706612125143 + ], + [ + -0.010947320073949565, + 8.41385706862771 + ] + ] + }, + { + "type": "line", + "version": 1766, + "versionNonce": 937627816, + "isDeleted": false, + "id": "c-4P1i2jYR8iecf6K1k2X", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": -1239.5050197679686, + "y": 178.57543164153304, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.016669064250991, + "height": 8.41385706862771, + "seed": 557657256, + "groupIds": [ + "CUC3YS9NLs07pOx5Lb6Az", + "3RoQ7jvIXGvmP-x527MGc" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.00572174417704, + 4.3706612125143 + ], + [ + -0.010947320073949565, + 8.41385706862771 + ] + ] + }, + { + "type": "text", + "version": 775, + "versionNonce": 1012472887, + "isDeleted": false, + "id": "Yx9G6iCcJXY-TrOu4TInH", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -734.022458081497, + "y": 354.32177576530097, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 275.6318664550781, + "height": 36, + "seed": 2101434280, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Self-Hosted Runners", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Self-Hosted Runners", + "lineHeight": 1.2857142857142858, + "baseline": 25 + }, + { + "type": "text", + "version": 707, + "versionNonce": 645867193, + "isDeleted": false, + "id": "ebcZo0xmb4rEWvjcjP48G", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -967.8455249796618, + "y": 222.09935500648697, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 182.64393615722656, + "height": 36, + "seed": 1032331944, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Manage fleet", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Manage fleet", + "lineHeight": 1.2857142857142858, + "baseline": 25 + }, + { + "type": "line", + "version": 1903, + "versionNonce": 1917727448, + "isDeleted": false, + "id": "h2IAOc1HvjAHCpDvnTlwI", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0.008516750252503869, + "x": -519.8907544855886, + "y": 246.3007655965817, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 38.357532662810776, + "height": 39.98584595309403, + "seed": 12422568, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 19.2864793354476, + 0.09105909911537124 + ], + [ + 19.304684350215307, + -10.634676758657868 + ], + [ + 38.357532662810776, + 10.473720182052507 + ], + [ + 19.043745805211625, + 29.35116919443616 + ], + [ + 19.325490081378387, + 19.65273387738712 + ], + [ + 0.1378379689554482, + 19.668124147660137 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "line", + "version": 2198, + "versionNonce": 1191511720, + "isDeleted": false, + "id": "DOJhL9EiM_2mcFVoihiDf", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 3.1127035944426, + "x": -699.1267173946699, + "y": 246.88980093109257, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 38.357532662810776, + "height": 39.98584595309403, + "seed": 806197416, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 19.2864793354476, + 0.09105909911537124 + ], + [ + 19.304684350215307, + -10.634676758657868 + ], + [ + 38.357532662810776, + 10.473720182052507 + ], + [ + 19.043745805211625, + 29.35116919443616 + ], + [ + 19.325490081378387, + 19.65273387738712 + ], + [ + 0.1378379689554482, + 19.668124147660137 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "text", + "version": 229, + "versionNonce": 1635155287, + "isDeleted": false, + "id": "dk1B6Alh-6U8kpyJ1mrUC", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": -1242.0397134561595, + "y": -146.13031506282698, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 149.575927734375, + "height": 36, + "seed": 790905768, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "GitHub App", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "GitHub App", + "lineHeight": 1.2857142857142858, + "baseline": 25 + }, + { + "type": "arrow", + "version": 307, + "versionNonce": 285077928, + "isDeleted": false, + "id": "MebWehEWzdFtf6cajcDfZ", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 80, + "angle": 0, + "x": -1167.4746941284593, + "y": -33.604472073508475, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 1.2088993528525407, + "height": 143.15727165779538, + "seed": 204312232, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808240666, + "link": null, + "locked": false, + "startBinding": { + "elementId": "gvlTdhY9vF1T5sAGvlM-K", + "focus": 1.1270691811193383, + "gap": 14.567551363868802 + }, + "endBinding": { + "elementId": "O_IqjSYNMnRbz7El-umgW", + "focus": 0.06856332031803856, + "gap": 9.49378038198418 + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + -0.6044496764262703, + 71.57863582889769 + ], + [ + -1.2088993528525407, + 143.15727165779538 + ] + ] + }, + { + "type": "text", + "version": 263, + "versionNonce": 1966860185, + "isDeleted": false, + "id": "gvlTdhY9vF1T5sAGvlM-K", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 80, + "angle": 0, + "x": -1153.410182145272, + "y": -19.036920709639674, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 220.75192260742188, + "height": 36, + "seed": 802519464, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "MebWehEWzdFtf6cajcDfZ", + "type": "arrow" + } + ], + "updated": 1702932324883, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Events and API", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Events and API", + "lineHeight": 1.2857142857142858, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 2962, + "versionNonce": 597813464, + "isDeleted": false, + "id": "a7I9fYj_NHVQ6NvYC85LC", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 2077.3076693814237, + "y": 285.5563618760185, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 304.9401622196817, + "height": 211.2826095052431, + "seed": 1642834344, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 1982, + "versionNonce": 1444875736, + "isDeleted": false, + "id": "H8YPKw7mPFmtmqzrqS9qi", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2199.314563327034, + "y": 141.222419225495, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 2098738344, + "groupIds": [ + "a-OoX4tbuao37tGEZ6Lwj", + "tdwBBrKvmXgF_1ro0o3Sm", + "4imvljK9nry_75LXP2EAI", + "i8aArLByfy71rMbFbY04l", + "7GWro_0OoUdlRW2zTtlU-", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1685, + "versionNonce": 1739559640, + "isDeleted": false, + "id": "LNnF3_x13sd_iOHPIsG6E", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2207.4982147950623, + "y": 170.32909372890043, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 947609512, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1738, + "versionNonce": 1592227800, + "isDeleted": false, + "id": "h16nl5KNH4DwyXLZQcMqb", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2248.555981844682, + "y": 170.2556586354346, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 339815080, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2355, + "versionNonce": 1339735256, + "isDeleted": false, + "id": "zldsqxwlQQ_X3l23el4Nf", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2224.479436141105, + "y": 166.64869847440622, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 722834856, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2428, + "versionNonce": 740123096, + "isDeleted": false, + "id": "eanF7c632oqEeoWmLe1_w", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5707963267948957, + "x": 2231.040931859843, + "y": 160.72153944131804, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1646567592, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2459, + "versionNonce": 314795736, + "isDeleted": false, + "id": "8JLW024XxlRxov2kg1U2D", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 2236.975335758091, + "y": 167.2403845403416, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 421153704, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2545, + "versionNonce": 543214552, + "isDeleted": false, + "id": "aiICg-V0cgCtGj8VnS28b", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.71238898038469, + "x": 2230.4229343321226, + "y": 173.1883984595517, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1512216232, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 1957, + "versionNonce": 1057591512, + "isDeleted": false, + "id": "UEpB6EvTVXgXZ-F541oY8", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2217.642890474028, + "y": 174.4028185186682, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 166298024, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 1973, + "versionNonce": 1985066456, + "isDeleted": false, + "id": "MJeBFZqzcHEFrU1Tp3A0N", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2240.2367391009657, + "y": 174.52568898030512, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 396037288, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 1948, + "versionNonce": 994917080, + "isDeleted": false, + "id": "dKreSTxB-wsP5FmheG5t0", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2211.521608778258, + "y": 170.3729131114198, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 753088424, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "line", + "version": 2052, + "versionNonce": 1083187160, + "isDeleted": false, + "id": "98UZ6tmVlV0yTybeGQcOT", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 2211.267951405246, + "y": 195.06049678357084, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 1575879336, + "groupIds": [ + "To2UFwNACH5N9A3Kgcreu", + "J05o3-ECyGRpXiJYxD9Qh", + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "text", + "version": 2270, + "versionNonce": 1177445592, + "isDeleted": false, + "id": "r-oPExycvLoMmY6fPKJ-7", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2112.347609559329, + "y": 211.3144430565913, + "strokeColor": "#343a40", + "backgroundColor": "transparent", + "width": 242.49977111816406, + "height": 24, + "seed": 1499950504, + "groupIds": [ + "27xLQQdgsbXi6_fPmq-X5" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "self-hosted, arm64, linux", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "self-hosted, arm64, linux", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 1430, + "versionNonce": 1773930968, + "isDeleted": false, + "id": "1UVkqKOAuZZEJGdO6Eq1S", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 2409.0573770885326, + "y": 521.7731821432103, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 637.2010586456353, + "height": 178.3817905555521, + "seed": 1040891816, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 827, + "versionNonce": 1984761560, + "isDeleted": false, + "id": "4hIhA2GDJ9qOzasQNct9N", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2142.973658949792, + "y": 306.66377310389464, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 175.6159210205078, + "height": 35, + "seed": 879813032, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "control plane", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "control plane", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 2991, + "versionNonce": 880112600, + "isDeleted": false, + "id": "YD8Xu4DtHwTL3aNhygMcA", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 2080.9727531924877, + "y": 64.73249635499621, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 1299.3620992093972, + "height": 187.37463292503452, + "seed": 1633246120, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1998, + "versionNonce": 977877208, + "isDeleted": false, + "id": "0VROusyBicI2qEHJlu5va", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2668.9682470939106, + "y": 78.31636479054404, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 105.08393859863281, + "height": 35, + "seed": 1744807592, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "webhook", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "webhook", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 1209, + "versionNonce": 995909080, + "isDeleted": false, + "id": "q63H__6pRM29Ifxqmx2ii", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2104.2404119872176, + "y": 398.7163000937936, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 260.59588623046875, + "height": 35, + "seed": 166131928, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Amzon Linux arm64", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Amzon Linux arm64", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 3129, + "versionNonce": 1489167064, + "isDeleted": false, + "id": "QA_pszmRQCI0zl2zCOPeQ", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 2408.457294598145, + "y": 285.4866218521914, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 304.9401622196817, + "height": 211.2826095052431, + "seed": 598155432, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 993, + "versionNonce": 1896925144, + "isDeleted": false, + "id": "KPGeRzNQxC4DRgcdkuQoy", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2473.9898590282983, + "y": 306.59403308006756, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 175.6159210205078, + "height": 35, + "seed": 105696168, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "control plane", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "control plane", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 1380, + "versionNonce": 1884949720, + "isDeleted": false, + "id": "ZC_7edpc8ocx-_aFsTKaA", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2452.0533522725336, + "y": 398.6465600699665, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 227.89190673828125, + "height": 35, + "seed": 2097485480, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Amzon Linux x64", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Amzon Linux x64", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 3240, + "versionNonce": 540193240, + "isDeleted": false, + "id": "FCwQtUQCCcweqggt6BlzX", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 2742.122432740991, + "y": 284.8417336841534, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 304.9401622196817, + "height": 211.2826095052431, + "seed": 480137640, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1105, + "versionNonce": 2007938776, + "isDeleted": false, + "id": "I7kOw_cJcgxbo7dsdwdk9", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2807.788422309359, + "y": 305.9491449120295, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 175.6159210205078, + "height": 35, + "seed": 456514728, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "control plane", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "control plane", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 1487, + "versionNonce": 1801591768, + "isDeleted": false, + "id": "VcJQjHTsHevdXxUZlFfSq", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2777.9334955552476, + "y": 398.0016719019285, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 243.12388610839844, + "height": 35, + "seed": 346294184, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Ubuntu Linux X64", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Ubuntu Linux X64", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 3298, + "versionNonce": 1029759192, + "isDeleted": false, + "id": "yDahuMQksHhZ2JuMdnhdb", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 3072.932272926041, + "y": 283.2183945025405, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 304.9401622196817, + "height": 211.2826095052431, + "seed": 784056744, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1163, + "versionNonce": 1295975896, + "isDeleted": false, + "id": "HbInIRtFZuyxk5DQqLqVp", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 3138.598262494409, + "y": 304.32580573041673, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 175.6159210205078, + "height": 35, + "seed": 1747274920, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "control plane", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "control plane", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "text", + "version": 1559, + "versionNonce": 1745914584, + "isDeleted": false, + "id": "WnwKzOVBgEMqo71YEjarc", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 3145.752737441013, + "y": 396.3783327203156, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 169.37193298339844, + "height": 35, + "seed": 1915058088, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Windows x64", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Windows x64", + "lineHeight": 1.25, + "baseline": 25 + }, + { + "type": "rectangle", + "version": 3310, + "versionNonce": 409563096, + "isDeleted": false, + "id": "wzq-CAGNoeOgm9-NprFmX", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 2076.8958261344915, + "y": 526.1055161086757, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 304.9401622196817, + "height": 174.6885415975437, + "seed": 350393768, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 3457, + "versionNonce": 1985852632, + "isDeleted": false, + "id": "LZKkU61_7nFmVg-WdGrmw", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 20, + "angle": 0, + "x": 3077.8423180123546, + "y": 523.8217224928991, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 304.9401622196817, + "height": 176.54315101872874, + "seed": 1496343768, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 1500, + "versionNonce": 2004965848, + "isDeleted": false, + "id": "5vA8V-jT5GNjQTiojE7PS", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2614.979607968624, + "y": 573.1919058326173, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 223.8039093017578, + "height": 70, + "seed": 1870925528, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Sync\nLinux x64 Agent", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Sync\nLinux x64 Agent", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "text", + "version": 1671, + "versionNonce": 1055416024, + "isDeleted": false, + "id": "e7vyxd7KqBh-_UICVg1cB", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 2105.3860071454455, + "y": 572.7169534688196, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 256.5079040527344, + "height": 70, + "seed": 569424856, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Sync\nLinux arm64 Agent", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Sync\nLinux arm64 Agent", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "text", + "version": 1576, + "versionNonce": 1831257048, + "isDeleted": false, + "id": "iMl7DnNSzlaUw_Vmx1DRX", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 100, + "angle": 0, + "x": 3099.237248281248, + "y": 573.819934611395, + "strokeColor": "#1971c2", + "backgroundColor": "transparent", + "width": 259.97991943359375, + "height": 70, + "seed": 1336141736, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 28, + "fontFamily": 1, + "text": "Sync\nWindows x64 Agent", + "textAlign": "center", + "verticalAlign": "top", + "containerId": null, + "originalText": "Sync\nWindows x64 Agent", + "lineHeight": 1.25, + "baseline": 60 + }, + { + "type": "line", + "version": 139, + "versionNonce": 1884326104, + "isDeleted": false, + "id": "7nmbhmY3vnNtz3VecNKvF", + "fillStyle": "hachure", + "strokeWidth": 4, + "strokeStyle": "solid", + "roughness": 2, + "opacity": 60, + "angle": 0, + "x": 2228.3993217422717, + "y": 232.46040573965126, + "strokeColor": "#343a40", + "backgroundColor": "transparent", + "width": 0, + "height": 0, + "seed": 1562794968, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ] + }, + { + "type": "rectangle", + "version": 2219, + "versionNonce": 1408871896, + "isDeleted": false, + "id": "rX5UzvzVzgeqhJPXswCVk", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2538.7276383024155, + "y": 138.6426543544813, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 674731992, + "groupIds": [ + "2uwztYv-hSP3dwaBB3H5E", + "kURWS4BiYGaV3Kra8psT4", + "cGeTlXPQJstXLdqdpxSeX", + "3IuRHfmfm-RxgJ_qV6EyF", + "hnJu7iuz97UlIFYQs4CYb", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1922, + "versionNonce": 288764632, + "isDeleted": false, + "id": "TyYOCYIhml4UXM_883iA-", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2546.9112897704445, + "y": 167.74932885788672, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 975625432, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 1975, + "versionNonce": 1587156952, + "isDeleted": false, + "id": "_tUxCrCnG_Zkj_AbAGKh4", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2587.969056820063, + "y": 167.6758937644209, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 937787864, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2592, + "versionNonce": 3759320, + "isDeleted": false, + "id": "uFk2sAoSBitBlSWr9KO24", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2563.892511116487, + "y": 164.0689336033925, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 814188248, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2665, + "versionNonce": 396886488, + "isDeleted": false, + "id": "UOQVqQHi7vjAVvbyEA7gR", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5707963267948957, + "x": 2570.4540068352244, + "y": 158.14177457030434, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 815852504, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2696, + "versionNonce": 1945765592, + "isDeleted": false, + "id": "mPqXxQQa2q3f-pnSnOjpy", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 2576.3884107334734, + "y": 164.6606196693279, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 306557144, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2782, + "versionNonce": 1640197080, + "isDeleted": false, + "id": "n52st9D_MvIumSIdxAabN", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.71238898038469, + "x": 2569.8360093075044, + "y": 170.608633588538, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1292490200, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2194, + "versionNonce": 2065182936, + "isDeleted": false, + "id": "QHfnPQknfuvW4h_xOMoQK", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2557.055965449409, + "y": 171.8230536476545, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 1174493912, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 2210, + "versionNonce": 2005685720, + "isDeleted": false, + "id": "P772mV-coJgPvaA5QiKVU", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2579.649814076348, + "y": 171.9459241092914, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 532692952, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 2185, + "versionNonce": 2083773144, + "isDeleted": false, + "id": "bxpGS4ucA71rQjov8aIzh", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2550.9346837536395, + "y": 167.79314824040608, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 173704408, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "line", + "version": 2289, + "versionNonce": 1805828056, + "isDeleted": false, + "id": "eogYKze5EHii9H0CESWpp", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 2550.6810263806283, + "y": 192.48073191255713, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 325331416, + "groupIds": [ + "INJgsu7FlK3du6IX8SiAF", + "Q4OZF3xLH7nDpPXsuCVB3", + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "text", + "version": 2575, + "versionNonce": 904725720, + "isDeleted": false, + "id": "Mom_qv3SwJHxrX1owXyVA", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2417.5977383530803, + "y": 211.26651044633536, + "strokeColor": "#343a40", + "backgroundColor": "transparent", + "width": 305.479736328125, + "height": 24, + "seed": 1978740440, + "groupIds": [ + "hPvS_vuxcCV2U7PYfqoRq" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "self-hosted, x64, linux, amazon", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "self-hosted, x64, linux, amazon", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2334, + "versionNonce": 682011096, + "isDeleted": false, + "id": "nyIlyzqyWtTP0v2Nd_KWw", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2871.754026544461, + "y": 136.70738014261195, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 347617496, + "groupIds": [ + "QwbZ0FXngaiCg7UbdVaHL", + "GP7CROYp4gYEpLlncQ4-0", + "fu-5vBGVZTu3mKDrHEPP7", + "Zr_weMG_LaCZ1Ro_Ajp_g", + "7Abb4Ki8akxfkVkZwLwKd", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2037, + "versionNonce": 1055108824, + "isDeleted": false, + "id": "ThNlicrTnuud9tXNMqs7z", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2879.93767801249, + "y": 165.81405464601738, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 1877695960, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2090, + "versionNonce": 1899500504, + "isDeleted": false, + "id": "3WBL3HN7Kp3IkesmFT7KY", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2920.9954450621085, + "y": 165.74061955255155, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 594666200, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2707, + "versionNonce": 95934680, + "isDeleted": false, + "id": "jSi0l1PAexRBIdYxiTWtB", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2896.9188993585326, + "y": 162.13365939152317, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 232769496, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2780, + "versionNonce": 1610022360, + "isDeleted": false, + "id": "xEEGxyBs2FdQ_9idVq77D", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5707963267948957, + "x": 2903.48039507727, + "y": 156.206500358435, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 457772248, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2811, + "versionNonce": 1359577816, + "isDeleted": false, + "id": "7cjH7ka9BpIfdUc_QYW0v", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 2909.414798975519, + "y": 162.72534545745856, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 356626904, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2897, + "versionNonce": 1736665048, + "isDeleted": false, + "id": "28IJN6yiCcLpYHJuqu9O-", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.71238898038469, + "x": 2902.862397549549, + "y": 168.67335937666866, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1927132888, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2309, + "versionNonce": 1064873176, + "isDeleted": false, + "id": "kHCd_g4PbU7Qm1lOq2nVS", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2890.0823536914545, + "y": 169.88777943578515, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 682695640, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 2325, + "versionNonce": 1383944664, + "isDeleted": false, + "id": "gMvgD5C07HqdT15pvCgBU", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2912.6762023183933, + "y": 170.01064989742207, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 2026889432, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 2300, + "versionNonce": 1202018008, + "isDeleted": false, + "id": "nUv3gRCXJUG1jnmZdP8CG", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 2883.961071995684, + "y": 165.85787402853674, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 1120798168, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "line", + "version": 2404, + "versionNonce": 1132772312, + "isDeleted": false, + "id": "dtKIR9-_qPfC-enSOidF0", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 2883.7074146226737, + "y": 190.5454577006878, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 1405061848, + "groupIds": [ + "rLw1c3jXUeLKMpTnImXl5", + "eas54ckXzB4yRHEEXAu0N", + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "text", + "version": 2697, + "versionNonce": 942637272, + "isDeleted": false, + "id": "hK5x69MOt3fN1OZ9AuIsA", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 2750.754230167319, + "y": 209.33123623446602, + "strokeColor": "#343a40", + "backgroundColor": "transparent", + "width": 299.15972900390625, + "height": 24, + "seed": 909668312, + "groupIds": [ + "uiH9OcenUBTI5XW4cBY1b" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "self-hosted, x64, linux, ubuntu", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "self-hosted, x64, linux, ubuntu", + "lineHeight": 1.2, + "baseline": 17 + }, + { + "type": "rectangle", + "version": 2384, + "versionNonce": 892970456, + "isDeleted": false, + "id": "SJ6YGl8WU9LXCi96az3e3", + "fillStyle": "cross-hatch", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3197.151734172458, + "y": 133.43744369480973, + "strokeColor": "#000000", + "backgroundColor": "#e6498088", + "width": 65.08084106445301, + "height": 65.08084106445301, + "seed": 20336296, + "groupIds": [ + "CPHL9_zU9yzik4bFUHxeH", + "Ao_9nuroMzEfXWBeITQhk", + "lJZqBlnRXf-_RJIIlR8Mx", + "fyuOJtKE4Whsiz2yO_gHN", + "bl5vqY5jDq34xEAwDwnx6", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2087, + "versionNonce": 934750936, + "isDeleted": false, + "id": "RQWSMluNjW3XsQ8A_879p", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3205.335385640487, + "y": 162.54411819821516, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 96876968, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "ellipse", + "version": 2140, + "versionNonce": 2050756568, + "isDeleted": false, + "id": "SqcAi-D1Lxy1afp1bfcV1", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3246.3931526901056, + "y": 162.47068310474933, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 8.117920455804926, + "height": 8.117920455804926, + "seed": 1730200744, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false + }, + { + "type": "line", + "version": 2757, + "versionNonce": 1155290328, + "isDeleted": false, + "id": "5_DNOq5hrlj00ETEKDkNE", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3222.3166069865297, + "y": 158.86372294372094, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1928458152, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2830, + "versionNonce": 1026292184, + "isDeleted": false, + "id": "Y4oDOXBLBWS__HMGcvJr_", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 1.5707963267948957, + "x": 3228.878102705267, + "y": 152.93656391063277, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 1634056872, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2861, + "versionNonce": 910098136, + "isDeleted": false, + "id": "eA7Xb1do1QOEWFyyaxual", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 3234.812506603516, + "y": 159.45540900965634, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 86517160, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2947, + "versionNonce": 11101144, + "isDeleted": false, + "id": "SPxrTLcx03WQt3Uz4WGa2", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 4.71238898038469, + "x": 3228.260105177546, + "y": 165.40342292886643, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 2.658716066016024, + "height": 14.901485256991352, + "seed": 2070229160, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 1.534250496037679, + 3.516089644932923 + ], + [ + 2.0434697529165025, + 7.61467595931855 + ], + [ + 1.302129499685611, + 11.595258942488735 + ], + [ + -0.615246313099522, + 14.901485256991352 + ] + ] + }, + { + "type": "line", + "version": 2359, + "versionNonce": 981412056, + "isDeleted": false, + "id": "o2DU2hTpAYaFfTo46CS1Y", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3215.4800613194516, + "y": 166.61784298798293, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 1539890088, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 2375, + "versionNonce": 525618648, + "isDeleted": false, + "id": "NW4g0zWkmcrYOgKf3UbnH", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3238.0739099463904, + "y": 166.74071344961985, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 5.842473884372846, + "height": 5.167099126652263, + "seed": 1753163432, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 5.816503304871627, + -0.053670945826642225 + ], + [ + 3.254730628247874, + -2.532485186304994 + ], + [ + 5.842473884372846, + -0.04842214250790278 + ], + [ + 3.0350803951419567, + 2.6346139403472693 + ] + ] + }, + { + "type": "line", + "version": 2350, + "versionNonce": 1480381144, + "isDeleted": false, + "id": "yNQC44-a97cdfbU_NUeIx", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 3209.358779623681, + "y": 162.58793758073452, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 1043599784, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "line", + "version": 2454, + "versionNonce": 1271707608, + "isDeleted": false, + "id": "h-TDoyC2tSbWZIhTBG86c", + "fillStyle": "solid", + "strokeWidth": 2, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 3.141592653589793, + "x": 3209.105122250671, + "y": 187.27552125288557, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 41.34963281275164, + "height": 17.109057844836915, + "seed": 68394152, + "groupIds": [ + "nAd9UKBvXPEUgYW-uF3-H", + "t7GyXVuBRnvOy0CjEIogJ", + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "startBinding": null, + "endBinding": null, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": null, + "points": [ + [ + 0, + 0 + ], + [ + 2.559970698127005, + -7.66093059073715 + ], + [ + 8.271070731353255, + -13.100012337621466 + ], + [ + 15.09486779216366, + -16.193976031908193 + ], + [ + 21.94229008411606, + -16.944786876248074 + ], + [ + 29.75087123626803, + -15.033447184450166 + ], + [ + 35.47649450941106, + -11.065217973307726 + ], + [ + 39.57403120169017, + -5.297544356691949 + ], + [ + 41.34963281275164, + 0.16427096858884305 + ] + ] + }, + { + "type": "text", + "version": 2824, + "versionNonce": 1847065816, + "isDeleted": false, + "id": "GfmRCkWhO-vCdwsoIYAGH", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 3102.9706208101834, + "y": 204.1357669181966, + "strokeColor": "#343a40", + "backgroundColor": "transparent", + "width": 248.9597625732422, + "height": 24, + "seed": 466208680, + "groupIds": [ + "sOfXfPibm0MKTyCgcsh0y" + ], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1702808552010, + "link": null, + "locked": false, + "fontSize": 20, + "fontFamily": 1, + "text": "self-hosted, x64, windows", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "self-hosted, x64, windows", + "lineHeight": 1.2, + "baseline": 17 + } + ], + "appState": { + "gridSize": null, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/docs/assets/multi-runner.dark.png b/docs/assets/multi-runner.dark.png new file mode 100644 index 0000000000..d11e0acfef Binary files /dev/null and b/docs/assets/multi-runner.dark.png differ diff --git a/docs/assets/multi-runner.light.png b/docs/assets/multi-runner.light.png new file mode 100644 index 0000000000..e85ce1d6f5 Binary files /dev/null and b/docs/assets/multi-runner.light.png differ diff --git a/docs/assets/runners.dark.png b/docs/assets/runners.dark.png new file mode 100644 index 0000000000..9379536233 Binary files /dev/null and b/docs/assets/runners.dark.png differ diff --git a/docs/assets/runners.light.png b/docs/assets/runners.light.png new file mode 100644 index 0000000000..2e3431105a Binary files /dev/null and b/docs/assets/runners.light.png differ diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000000..1a5af903f4 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,244 @@ +# Configuration + +## Configuration considerations + +To be able to support a number of use-cases, the module has quite a lot of configuration options. We tried to choose reasonable defaults. Several examples also show the main cases of how to configure the runners. + +- Org vs Repo level. You can configure the module to connect the runners in GitHub on an org level and share the runners in your org, or set the runners on repo level and the module will install the runner to the repo. There can be multiple repos but runners are not shared between repos. +- Multi-Runner module. This modules allows you to create multiple runner configurations with a single webhook and single GitHub App to simplify deployment of different types of runners. Check the detailed module [documentation](modules/public/multi-runner.md) for more information or checkout the [multi-runner example](examples/multi-runner.md). +- Workflow job event. You can configure the webhook in GitHub to send workflow job events to the webhook. Workflow job events were introduced by GitHub in September 2021 and are designed to support scalable runners. We advise using the workflow job event when possible. +- Linux vs Windows. You can configure the OS types linux and win. Linux will be used by default. +- Re-use vs Ephemeral. By default runners are re-used, until detected idle. Once idle they will be removed from the pool. To improve security we are introducing ephemeral runners. Those runners are only used for one job. Ephemeral runners only work in combination with the workflow job event. For ephemeral runners the lambda requests a JIT (just in time) configuration via the GitHub API to register the runner. [JIT configuration](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-just-in-time-runners) is limited to ephemeral runners (and currently not supported by GHES). For non-ephemeral runners, a registration token is always requested. In both cases the configuration is made available to the instance via the same SSM parameter. To disable JIT configuration for ephemeral runners set `enable_jit_config` to `false`. We also suggest using a pre-build AMI to improve the start time of jobs for ephemeral runners. +- GitHub Cloud vs GitHub Enterprise Server (GHES). The runners support GitHub Cloud as well GitHub Enterprise Server. For GHES, we rely on our community for support and testing. We at Philips have no capability to test GHES ourselves. +- Spot vs on-demand. The runners use either the EC2 spot or on-demand life cycle. Runners will be created via the AWS [CreateFleet API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html). The module (scale up lambda) will request via the CreateFleet API to create instances in one of the subnets and of the specified instance types. +- ARM64 support via Graviton/Graviton2 instance-types. When using the default example or top-level module, specifying `instance_types` that match a Graviton/Graviton 2 (ARM64) architecture (e.g. a1, t4g or any 6th-gen `g` or `gd` type), you must also specify `runner_architecture = "arm64"` and the sub-modules will be automatically configured to provision with ARM64 AMIs and leverage GitHub's ARM64 action runner. See below for more details. + +## AWS SSM Parameters + +The module uses the AWS System Manager Parameter Store to store configuration for the runners, as well as registration tokens and secrets for the Lambdas. Paths for the parameters can be configured via the variable `ssm_paths`. The location of the configuration parameters is retrieved by the runners via the instance tag `ghr:ssm_config_path`. The following default paths will be used. Tokens or JIT config stored in the token path will be deleted after retrieval by instance, data not deleted after a day will be deleted by a SSM housekeeper lambda. + +| Path | Description | +| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ssm_paths.root/var.prefix?/app/` | App secrets used by Lambda's | +| `ssm_paths.root/var.prefix?/runners/config/` | Configuration parameters used by runner start script | +| `ssm_paths.root/var.prefix?/runners/tokens/` | Either JIT configuration (ephemeral runners) or registration tokens (non ephemeral runners) generated by the control plane (scale-up lambda), and consumed by the start script on the runner to activate / register the runner. | +| `ssm_paths.root/var.prefix?/webhook/runner-matcher-config` | Runner matcher config used by webhook to decide the target for the webhook event. | +Available configuration parameters: + +| Parameter name | Description | +| ------------------- | ----------------------------------------------------------- | +| `agent_mode` | Indicates if the agent is running in ephemeral mode or not. | +| `enable_cloudwatch` | Configuration for the cloudwatch agent to stream logging. | +| `run_as` | The user used for running the GitHub action runner agent. | +| `token_path` | The path where tokens are stored. | + +## Encryption + +The module supports two scenarios to manage environment secrets and private keys of the Lambda functions. + +### Managed KMS key (default) + +This is the default, no additional configuration is required. + +### Provided KMS key + +You have to create and configure you KMS key. The module will use the context with key: `Environment` and value `var.environment` as encryption context. + +```hcl +resource "aws_kms_key" "github" { + is_enabled = true +} + +module "runners" { + + ... + kms_key_arn = aws_kms_key.github.arn + ... +``` + +## Pool + +The module supports two options for keeping a pool of runners. One is via a pool which only supports org-level runners, the second option is [keeping runners idle](#idle-runners). + +The pool is introduced in combination with the ephemeral runners and is primarily meant to ensure if any event is unexpectedly dropped and no runner was created, the pool can pick up the job. The pool is maintained by a lambda. Each time the lambda is triggered a check is performed to ensure the number of idle runners managed by the module matches the expected pool size. If not, the pool will be adjusted. Keep in mind that the scale down function is still active and will terminate instances that are detected as idle. + +```hcl +pool_runner_owner = "my-org" # Org to which the runners are added +pool_config = [{ + size = 20 # size of the pool + schedule_expression = "cron(* * * * ? *)" # cron expression to trigger the adjustment of the pool +}] +``` + +The pool is NOT enabled by default and can be enabled by setting at least one object of the pool config list. The [ephemeral example](examples/ephemeral.md) contains configuration options (commented out). + +## Idle runners + +The module will scale down to zero runners by default. By specifying a `idle_config` config, idle runners can be kept active. The scale down lambda checks if any of the cron expressions matches the current time with a margin of 5 seconds. When there is a match, the number of runners specified in the idle config will be kept active. In case multiple cron expressions match, the first one will be used. Below is an idle configuration for keeping runners active from 9:00am to 5:59pm on working days. The [cron expression generator by Cronhub](https://crontab.cronhub.io/) is a great resource to set up your idle config. + +By default, the oldest instances are evicted. This helps keep your environment up-to-date and reduce problems like running out of disk space or RAM. Alternatively, if your older instances have a long-living cache, you can override the `evictionStrategy` to `newest_first` to evict the newest instances first instead. + +```hcl +idle_config = [{ + cron = "* * 9-17 * * 1-5" + timeZone = "Europe/Amsterdam" + idleCount = 2 + # Defaults to 'oldest_first' + evictionStrategy = "oldest_first" +}] +``` + +_**Note**_: When using Windows runners, we recommend keeping a few runners warmed up due to the minutes-long cold start time. + +#### Supported config + +Cron expressions are parsed by [cron-parser](https://github.com/harrisiirak/cron-parser#readme). The supported syntax. + +```bash +* * * * * * +┬ ┬ ┬ ┬ ┬ ┬ +│ │ │ │ │ | +│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun) +│ │ │ │ └───── month (1 - 12) +│ │ │ └────────── day of month (1 - 31) +│ │ └─────────────── hour (0 - 23) +│ └──────────────────── minute (0 - 59) +└───────────────────────── second (0 - 59, optional) +``` + +For time zones please check [TZ database name column](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the supported values. + +## Ephemeral runners + +You can configure runners to be ephemeral, in which case runners will be used only for one job. The feature should be used in conjunction with listening for the workflow job event. Please consider the following: + +- The scale down lambda is still active, and should only remove orphan instances. But there is no strict check in place. So ensure you configure the `minimum_running_time_in_minutes` to a value that is high enough to get your runner booted and connected to avoid it being terminated before executing a job. +- The messages sent from the webhook lambda to the scale-up lambda are by default delayed by SQS, to give available runners a chance to start the job before the decision is made to scale more runners. For ephemeral runners there is no need to wait. Set `delay_webhook_event` to `0`. +- All events in the queue will lead to a new runner created by the lambda. By setting `enable_job_queued_check` to `true` you can enforce a rule of only creating a runner if the event has a correlated queued job. Setting this can avoid creating useless runners. For example, a job getting cancelled before a runner was created or if the job was already picked up by another runner. We suggest using this in combination with a pool. +- To ensure runners are created in the same order GitHub sends the events, by default we use a FIFO queue. This is mainly relevant for repo level runners. For ephemeral runners you can set `enable_fifo_build_queue` to `false`. +- Errors related to scaling should be retried via SQS. You can configure `job_queue_retention_in_seconds` and `redrive_build_queue` to tune the behavior. We have no mechanism to avoid events never being processed, which means potentially no runner gets created and the job in GitHub times out in 6 hours. + +The example for [ephemeral runners](examples/ephemeral.md) is based on the [default example](examples/default.md). Have look at the diff to see the major configuration differences. + +## Prebuilt Images + +This module also allows you to run agents from a prebuilt AMI to gain faster startup times. The module provides several examples to build your own custom AMI. To remove old images, an [AMI housekeeper module](modules/public/ami-housekeeper.md) can be used. See the [AMI examples](ami-examples/index.md) for more details. + +## Logging + +The module uses [AWS Lambda Powertools](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/) for logging. By default the log level is set to `info`, by setting the log level to `debug` the incoming events of the Lambda are logged as well. + +Log messages contains at least the following keys: + +- `messages`: The logged messages +- `environment`: The environment prefix provided via Terraform +- `service`: The lambda +- `module`: The TypeScript module writing the log message +- `function-name`: The name of the lambda function (prefix + function name) +- `github`: Depending on the lambda, contains GitHub context +- `runner`: Depending on the lambda, specific context related to the runner + +An example log message of the scale-up function: + +```json +{ + "level": "INFO", + "message": "Received event", + "service": "runners-scale-up", + "timestamp": "2023-03-20T08:15:27.448Z", + "xray_trace_id": "1-6418161e-08825c2f575213ef760531bf", + "module": "scale-up", + "region": "eu-west-1", + "environment": "my-linux-x64", + "aws-request-id": "eef1efb7-4c07-555f-9a67-b3255448ee60", + "function-name": "my-linux-x64-scale-up", + "runner": { + "type": "Repo", + "owner": "test-runners/multi-runner" + }, + "github": { + "event": "workflow_job", + "workflow_job_id": "1234" + } +} +``` + +## Tracing + +The distributed architecture of this application can make it difficult to troubleshoot. We support the option to enable tracing for all the lambda functions created by this application. To enable tracing, you can provide the `tracing_config` option inside the root module or inner modules. + +This tracing config generates timelines for following events: + +- Basic lifecycle of lambda function +- Traces for Github API calls (can be configured by capture_http_requests). +- Traces for all AWS SDK calls + +This feature has been disabled by default. + +### Multiple runner module in your AWS account + +The watcher will act on all spot termination notificatins and log all onses relevant to the runner module. Therefor we suggest to only deploy the watcher once. You can either deploy the watcher by enabling in one of your deployments or deploy the watcher as a stand alone module. + + +## Debugging + +In case the setup does not work as intended, trace the events through this sequence: + +- In the GitHub App configuration, the Advanced page displays all webhook events that were sent. +- In AWS CloudWatch, every lambda has a log group. Look at the logs of the `webhook` and `scale-up` lambdas. +- In AWS SQS you can see messages available or in flight. +- Once an EC2 instance is running, you can connect to it in the EC2 user interface using Session Manager (use `enable_ssm_on_runners = true`). Check the user data script using `cat /var/log/user-data.log`. By default several log files of the instances are streamed to AWS CloudWatch, look for a log group named `/runners`. In the log group you should see at least the log streams for the user data installation and runner agent. +- Registered instances should show up in the Settings - Actions page of the repository or organization (depending on the installation mode). + +## Experimental features + +### Termination watcher + +This feature is in early stage and therefore disabled by default. + +The termination watcher is currently watching for spot termination notifications. The module is only taken events into account for instances tagged with `ghr:environment` by default when deployment the module as part of one of the main modules (root or multi-runner). The module can also be deployed stand-alone, in that case the tag filter needs to be tunned. + +- Logs: The module will log all termination notifications. For each warning it will look up instance details and log the environment, instance type and time the instance is running. As well some other details. +- Metrics: Metrics are disabled by default, this to avoid costs. Once enabled a metric will be created for each warning with at least dimensions for the environment and instance type. THe metric name space can be configured via the variables. The metric name used is `SpotInterruptionWarning`. + +#### Log example + +Below an example of the the log messages created. + +``` +{ + "level": "INFO", + "message": "Received spot notification warning:", + "environment": "default", + "instanceId": "i-0039b8826b3dcea55", + "instanceType": "c5.large", + "instanceLaunchTime": "2024-03-15T08:10:34.000Z", + "instanceRunningTimeInSeconds": 68, + "tags": [ + { + "Key": "ghr:environment", + "Value": "default" + } + ... all tags ... + ] +} +``` + +### Queue to publish workflow job events + +This queue is an experimental feature to allow you to receive a copy of the wokflow_jobs events sent by the GitHub App. This can be used to calculate a matrix or monitor the system. + +To enable the feature set `enable_workflow_job_events_queue = true`. Be aware though, this feature is experimental! + +Messages received on the queue are using the same format as published by GitHub wrapped in a property `workflowJobEvent`. + +``` +export interface GithubWorkflowEvent { + workflowJobEvent: WorkflowJobEvent; +} +``` + +This extensible format allows more fields to be added if needed. +You can configure the queue by setting properties to `workflow_job_events_queue_config` + +NOTE: By default, a runner AMI update requires a re-apply of this terraform config (the runner AMI ID is looked up by a terraform data source). To avoid this, you can use `ami_id_ssm_parameter_name` to have the scale-up lambda dynamically lookup the runner AMI ID from an SSM parameter at instance launch time. Said SSM parameter is managed outside of this module (e.g. by a runner AMI build workflow). diff --git a/docs/examples/arm64.md b/docs/examples/arm64.md new file mode 100644 index 0000000000..7b281e4a07 --- /dev/null +++ b/docs/examples/arm64.md @@ -0,0 +1 @@ +--8<-- "examples/arm64/README.md" diff --git a/docs/examples/default.md b/docs/examples/default.md new file mode 100644 index 0000000000..7d549b1176 --- /dev/null +++ b/docs/examples/default.md @@ -0,0 +1 @@ +--8<-- "examples/default/README.md" diff --git a/docs/examples/ephemeral.md b/docs/examples/ephemeral.md new file mode 100644 index 0000000000..2037f0769e --- /dev/null +++ b/docs/examples/ephemeral.md @@ -0,0 +1 @@ +--8<-- "examples/ephemeral/README.md" diff --git a/docs/examples/index.md b/docs/examples/index.md new file mode 100644 index 0000000000..6cf3bb15a5 --- /dev/null +++ b/docs/examples/index.md @@ -0,0 +1,11 @@ +# Examples + +Examples are located in the [examples](https://github.com/philips-labs/terraform-aws-github-runner/tree/main/examples) directory. The following examples are provided: + +- _[Default](default.md)_: The default example of the module +- _[ARM64](arm64.md)_: Example usage with ARM64 architecture +- _[Ephemeral](ephemeral.md)_: Example usages of ephemeral runners based on the default example. +- _[Multi Runner](multi-runner.md)_ : Example usage of creating a multi runner which creates multiple runners/ configurations with a single deployment +- _[Permissions boundary](permissions-boundary.md)_: Example usages of permissions boundaries. +- _[Prebuilt Images](prebuilt.md)_: Example usages of deploying runners with a custom prebuilt image. +- _[Windows](windows.md)_: Example usage of creating a runner using Windows as the OS. diff --git a/docs/examples/lambda-download.md b/docs/examples/lambda-download.md new file mode 100644 index 0000000000..b8d6bea9d9 --- /dev/null +++ b/docs/examples/lambda-download.md @@ -0,0 +1 @@ +--8<-- "examples/lambdas-download/README.md" diff --git a/docs/examples/multi-runner.md b/docs/examples/multi-runner.md new file mode 100644 index 0000000000..c77d453a20 --- /dev/null +++ b/docs/examples/multi-runner.md @@ -0,0 +1 @@ +--8<-- "examples/multi-runner/README.md" diff --git a/docs/examples/permissions-boundary.md b/docs/examples/permissions-boundary.md new file mode 100644 index 0000000000..094ad59475 --- /dev/null +++ b/docs/examples/permissions-boundary.md @@ -0,0 +1 @@ +--8<-- "examples/permissions-boundary/README.md" diff --git a/docs/examples/prebuilt.md b/docs/examples/prebuilt.md new file mode 100644 index 0000000000..aee7d64bb7 --- /dev/null +++ b/docs/examples/prebuilt.md @@ -0,0 +1 @@ +--8<-- "examples/prebuilt/README.md" diff --git a/docs/examples/termination-watcher.md b/docs/examples/termination-watcher.md new file mode 100644 index 0000000000..42573030a7 --- /dev/null +++ b/docs/examples/termination-watcher.md @@ -0,0 +1 @@ +--8<-- "examples/termination-watcher/README.md" diff --git a/docs/examples/windows.md b/docs/examples/windows.md new file mode 100644 index 0000000000..967dd7ed69 --- /dev/null +++ b/docs/examples/windows.md @@ -0,0 +1 @@ +--8<-- "examples/windows/README.md" diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000000..f13c84764f --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,149 @@ +# Getting started + +Terraform examples are available for different use-cases for example multiple runners, ephemeral runners, and windows. For more details see the [examples](examples/index.md). + +The module supports two main scenarios for creating runners. Repository level runners will be dedicated to only one repository, no other repository can use the runner. At the organization level you can use the runner(s) for all repositories within the organization. See [GitHub self-hosted runner instructions](https://help.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) for more information. Before starting the deployment you have to choose one option. + +The setup guide below is a generic direction. There are many choices you can make, and there is no right way. For example we deploy ephemeral runners for both Linux and WIndows with packer pre-built AMI's that are automatically updated. Deployment is done with GitHub actions, Terragrunt and terraform. The lambda's we sync to AWS S3. For the major fleet we have a tiny pool to let start jobs quickly. + +## Required tools + +The following tools are a minimum requirement. We advise to deploy the stack via a CI/CD pipeline. + +- Terraform +- Bash shell or compatible +- Docker (optional, to build lambdas without node). +- AWS cli (optional) +- Node and yarn to build the Lambda's (or download via Release). + +## Setup guide + +The setup consists of running Terraform to create all AWS resources and manually configuring the GitHub App. The Terraform module requires configuration from the GitHub App and the GitHub app requires output from Terraform. Therefore you first create the GitHub App and configure the basics, then run Terraform, and afterwards finalize the configuration of the GitHub App. + +### Setup GitHub App (part 1) + +Go to GitHub and [create a new app](https://docs.github.com/en/developers/apps/creating-a-github-app). Be aware you can create apps for your organization or for a user. For now we only support organization level apps. + +1. Create an app in Github +2. Choose a name +3. Choose a website (mandatory, not required for the module). +4. Disable the webhook for now (we will configure this later or create an alternative webhook). +5. Permissions for all runners: + - Repository: + - `Actions`: Read-only (check for queued jobs) + - `Checks`: Read-only (receive events for new builds) + - `Metadata`: Read-only (default/required) +6. _Permissions for repo level runners only_: + - Repository: + - `Administration`: Read & write (to register runner) +7. _Permissions for organization level runners only_: + - Organization + - `Self-hosted runners`: Read & write (to register runner) +8. Save the new app. +9. On the General page, make a note of the "App ID" and "Client ID" parameters. +10. Generate a new private key and save the `app.private-key.pem` file. + +### Setup terraform module + +#### Download lambdas + +To apply the terraform module, the compiled lambdas (.zip files) need to be available either locally or in an S3 bucket. They can either be downloaded from the GitHub release page or built locally. + +To read the files from S3, set the `lambda_s3_bucket` variable and the specific object key for each lambda. + +The lambdas can be downloaded manually from the [release page](https://github.com/philips-labs/terraform-aws-github-runner/releases) or using the [download-lambda](modules/public/download-lambda.md) terraform module (requires `curl` to be installed on your machine). In the `download-lambda` directory, run `terraform init && terraform apply`. The lambdas will be saved to the same directory. + +For local development you can build all the lambdas at once using `.ci/build.sh` or individually using `yarn dist`. + +#### Service-linked role + +To create spot instances the `AWSServiceRoleForEC2Spot` role needs to be added to your account. You can do that manually by following the [AWS docs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-requests.html#service-linked-roles-spot-instance-requests). To use terraform for creating the role, either add the following resource or let the module manage the service linked role by setting `create_service_linked_role_spot` to `true`. Be aware this is an account global role, so maybe you don't want to manage it via a specific deployment. + +```hcl +resource "aws_iam_service_linked_role" "spot" { + aws_service_name = "spot.amazonaws.com" +} +``` + +#### Terraform module + +Next create a second terraform workspace and initiate the module, or adapt one of the [examples](examples/index.md). + +Note that `github_app.key_base64` needs to be a base64-encoded string of the `.pem` file i.e. the output of `base64 app.private-key.pem`. The decoded string can either be a multiline value or a single line value with new lines represented with literal `\n` characters. + +```hcl +module "github-runner" { + source = "philips-labs/github-runner/aws" + version = "REPLACE_WITH_VERSION" + + aws_region = "eu-west-1" + vpc_id = "vpc-123" + subnet_ids = ["subnet-123", "subnet-456"] + + prefix = "gh-ci" + + github_app = { + key_base64 = "base64string" + id = "1" + webhook_secret = "webhook_secret" + } + + webhook_lambda_zip = "lambdas-download/webhook.zip" + runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip" + runners_lambda_zip = "lambdas-download/runners.zip" + enable_organization_runners = true +} +``` + +Run terraform by using the following commands + +```bash +terraform init +terraform apply +``` + +The terraform output displays the API gateway url (endpoint) and secret, which you need in the next step. + +The lambda for syncing the GitHub distribution to S3 is triggered via CloudWatch (by default once per hour). After deployment the function is triggered via S3 to ensure the distribution is cached. + +### Setup the webhook / GitHub App (part 2) + +At this point you have two options. Either create a separate webhook (enterprise, +org, or repo), or create a webhook in the App. + +#### Option 1: Webhook + +1. Create a new webhook at the repo level for repo level runners, or org (or enterprise level) for org level runners. +2. Provide the webhook url, which should be part of the output of terraform. +3. Provide the webhook secret (`terraform output -raw `). +4. Ensure the content type is `application/json`. +5. In the "Permissions & Events" section and then "Subscribe to Events" subsection, check either "Workflow Job" or "Check Run" (choose only one option!!!). +6. In the "Install App" section, install the App in your organization, either in all or in selected repositories. + +#### Option 2: App + +Go back to the GitHub App and update the following settings. + +1. Enable the webhook. +2. Provide the webhook url, should be part of the output of terraform. +3. Provide the webhook secret (`terraform output -raw `). +4. In the "Permissions & Events" section and then "Subscribe to Events" subsection, check either "Workflow Job" or "Check Run" (choose only one option!!!). + +#### Install GitHub app + +Finally you need to ensure the app is installed to all or selected repositories. + +Go back to the GitHub App and update the following settings. + +1. In the "Install App" section, install the App in your organization, either in all or in selected repositories. + + +## Debugging + +In case the setup does not work as intended follow the trace of events: + +- In the GitHub App configuration, the Advanced page displays all webhook events that were sent. +- In AWS CloudWatch, every lambda has a log group. Look at the logs of the `webhook` and `scale-up` lambdas. +- In AWS SQS you can see messages available or in flight. +- Once an EC2 instance is running, you can connect to it in the EC2 user interface using Session Manager (use `enable_ssm_on_runners = true`). Check the user data script using `cat /var/log/user-data.log`. By default several log files of the instances are streamed to AWS CloudWatch, look for a log group named `/runners`. In the log group you should see at least the log streams for the user data installation and runner agent. +- Registered instances should show up in the Settings - Actions page of the repository or organization (depending on the installation mode). diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..38d7d8cb95 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,100 @@ +# GitHub Self-Hosted on AWS on Spot Instances + +This [Terraform](https://www.terraform.io/) module creates the required infrastructure needed to host [GitHub Actions](https://github.com/features/actions) self-hosted, auto-scaling runners on [AWS spot instances](https://aws.amazon.com/ec2/spot/). It provides the required logic to handle the life cycle for scaling up and down using a set of AWS Lambda functions. Runners are scaled down to zero to avoid costs when no workflows are active. + +![Architecture](assets/runners.light.png#only-light) +![Architecture](assets/runners.dark.png#only-dark) + +## Motivation + +GitHub Actions `self-hosted` runners provide a flexible option to run CI workloads on the infrastructure of your choice. However, currently GitHub does not provide tooling to automate the creation and scaling of action runners. This module creates the AWS infrastructure to host action runners on spot instances. It also provides lambda modules to orchestrate the life cycle of the action runners. + +Lambda was selected as the preferred runtime for two primary reasons. Firstly, it enables the development of compact components with limited access to AWS and GitHub. Secondly, it offers a scalable configuration with minimal expenses, applicable at both the repository and organizational levels. The Lambda functions will be responsible for provisioning Linux-based EC2 instances equipped with Docker to handle CI workloads compatible with Linux and/or Docker. The primary objective is to facilitate Docker-based workloads. + +A pertinent question may arise: why not opt for Kubernetes? The current strategy aligns closely with the implementation of GitHub's action runners. The chosen approach involves installing the runner on a host where the necessary software is readily available, maintaining proximity to GitHub's existing practices. Another viable option could be AWS Auto Scaling groups. However, this alternative usually demands broader permissions at the instance level from GitHub. Additionally, managing the scaling process, both up and down, becomes a non-trivial task in this scenario. + +## Overview + +The module is designed to be used in a GitHub organization. It can also be used in a GitHub repository, but this not supports all features. The module is receiving GitHub webhook events for the `workflow_job` event. The module will create a new runner if the event is for a workflow that requires a runner, and no runner is available. Alteratively the module can be configured as ephemeral runners. In this case the module will create a new runner for each workflow job event. + +For ephemeral runners a pool is can be configured. The pool maintains a minimum number of runners based on a schedule. The pool works only for org level runners. + +For non ephemeral runners with the idle config the module will avoid scaling down back to zero. Instead it will maintain a minimum number of runners based on a schedule. This avoids the need to scale up when a new workflow is triggered. + + +## Detailed design + +The diagram below shows the architecture of the module, groups are indicating the different components. Ww will go through the components in the following sections. + +![Architecture](assets/aws-architecture.light.png#only-light) +![Architecture](assets/aws-architecture.dark.png#only-dark) + +### Webhook + +The moment a GitHub action workflow requiring a `self-hosted` runner is triggered, GitHub will try to find a runner which can execute the workload. See [additional notes](additional_notes.md) for how the selection is made. This module reacts to GitHub's [`workflow_job` event](https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/webhook-events-and-payloads#workflow_job) for the triggered workflow and creates a new runner if necessary. + +For receiving the `workflow_job` event by the webhook (lambda), a webhook needs to be created in GitHub. The same app as for API calls can be used to create the webhook. Or a dedicated webhook can be defined. + +- Create a GitHub app, define a webhook and subscribe the app to the `workflow_job` event. +- Create a webhook on enterprise, org or repo level, define a webhook and subscribe the app to the `workflow_job` event. + +In AWS an [API gateway](https://docs.aws.amazon.com/apigateway/index.html) endpoint is created that is able to receive the GitHub webhook events via HTTP post. The gateway triggers the webhook lambda which will verify the signature of the event. This check guarantees the event is sent by the GitHub App. The lambda only handles `workflow_job` events with status `queued` and matching the runner labels. The accepted events are posted on a SQS queue. Messages on this queue will be delayed for a configurable amount of seconds (default 30 seconds) to give the available runners time to pick up this build. + +### Control plane + +The "Scale Up Runner" Lambda actively monitors the SQS queue, processing incoming events. The Lambda conducts a series of checks to determine the necessity of creating a new EC2 spot instance. For instance, it refrains from creating an instance if a build is already initiated by an existing runner or if the maximum allowable number of runners has been reached. + +The Lambda first requests a JIT configuration or registration token from GitHub, which is needed later by the runner to register itself. This avoids the case that the EC2 instance, which later in the process will install the agent, needs administration permissions to register the runner. Next, the EC2 spot instance is created via the launch template. The launch template defines the specifications of the required instance and contains a [`user_data`](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) script. This script will install the required software and configure it. The configuration for the runner is shared via EC2 tags and the parameter store (SSM), from which the user data script will fetch it and delete it once it has been retrieved. Once the user data script is finished, the action runner should be online, and the workflow will start in seconds. + +The current method for scaling down runners employs a straightforward approach: at predefined intervals, the Lambda conducts a thorough examination of each runner (instance) to assess its activity. If a runner is found to be idle, it is deregistered from GitHub, and the associated AWS instance is terminated. For ephemeral runners the the instance is terminated immediately after the workflow is finished. To avoid orphaned runners the scale down lambda is active in this cae as well. + +### Pool + +The pool is only designed for org level runners in ephemeral mode. The pool will maintain a minimum number of runners based on a schedule. Keeping a small pool can help to start jobs faster and avoid missed events are causing long hanging jobs. The pool is opt in, it will not be created by default. + +### Agent sync + +To address potential delays in downloading the GitHub Action Runner distribution, a lambda function has been implemented to synchronize the action runner binary from GitHub to an S3 bucket. This ensures that the EC2 instance can retrieve the distribution from the S3 bucket, mitigating the need to rely on internet downloads, which can occasionally take more than 10 minutes. The best way to speed up instance startup is to use a pre-built AMI with the runner binary already installed. See the [examples](examples/index.md) for more details. + +### SSM housekeeping + +The control plane (scale up lambda) will store the runner registration configuration in the SSM parameter store. The token is stored in a secure string parameter. The token is deleted after the runner has registered itself. The token is also deleted after a configurable amount of time (default 24 hours). This house keeping ensures that your SSM parameter store does not fill up with old configuration. + +### AMI cleaner + +The AMI cleaner is a lambda that will clean up AMIs that are older than a configurable amount of days. This is useful when using the AMI builder to create AMIs. The cleaner will also check which AMIs are used the latest version of the launch template. And you can provide SSM config paths pointing to AMI IDs. The cleaner will not delete these AMIs. The AMI cleaner is opt in, it will not be created by default. + +### Instance Termination Watcher + +> This feature is Beta, changes will not trigger a major release as long in beta. + +The Instance Termination Watcher is creating log and optional metrics for termination of instances. Currently only spot termination warnings are watched. See [configuration](configuration/) for more details. + +### Security + +Sensitive information such as secrets and private keys is stored securely in the SSM Parameter Store. These values undergo encryption using either the default KMS key for SSM or a custom KMS key, depending on the specified configuration. + +Permission are managed in several places. Below are the most important ones. For details check the Terraform sources. + +- The GitHub App requires access to actions and to publish `workflow_job` events to the AWS webhook (API gateway). +- The scale up lambda should have access to EC2 for creating and tagging instances. +- The scale down lambda should have access to EC2 to terminate instances. + +Besides these permissions, the lambdas also need permission to CloudWatch (for logging and scheduling), SSM and S3. For more details about the required permissions see the [documentation](modules/public/setup-iam-permissions.md) of the IAM module which uses permission boundaries. + +## Terraform main modules + +Currently we support two main modules. The `runners` module is the main module for creating runners. And the 'multi-runner' module is a wrapper around the `runners` module to create multiple runners in one go. The `multi-runner` module is useful for creating runners for multiple repositories or organizations. + +Both modules are built on top of the same base modules. When using the multi-runner module you can deploy different runners with only one deployment. + +![multi-runner](assets/multi-runner.light.png#only-light) +![multi-runner](assets/multi-runner.dark.png#only-dark) + +## Recommendations + +The module contains a lot of configuration options. The default values are a good starting point. But you may want to tweak some of the values. Below are some recommendations. We suggest the following configuration for the runners: + +- Use the multi-runner module to create multiple runners in one go. +- Use the ephemeral runners for org level runners. To improve the security of your runners. +- Use pre-built AMIs to speed up the startup of your runners. diff --git a/docs/modules/internal/runner-binaries-syncer.md b/docs/modules/internal/runner-binaries-syncer.md new file mode 100644 index 0000000000..8eacd88f7b --- /dev/null +++ b/docs/modules/internal/runner-binaries-syncer.md @@ -0,0 +1 @@ +--8<-- "modules/runner-binaries-syncer/README.md" diff --git a/docs/modules/internal/runners.md b/docs/modules/internal/runners.md new file mode 100644 index 0000000000..fe5dfc518f --- /dev/null +++ b/docs/modules/internal/runners.md @@ -0,0 +1 @@ +--8<-- "modules/runners/README.md" diff --git a/docs/modules/internal/ssm.md b/docs/modules/internal/ssm.md new file mode 100644 index 0000000000..b652faa68c --- /dev/null +++ b/docs/modules/internal/ssm.md @@ -0,0 +1 @@ +--8<-- "modules/ssm/README.md" diff --git a/docs/modules/internal/webhook-github-app.md b/docs/modules/internal/webhook-github-app.md new file mode 100644 index 0000000000..138a539e8c --- /dev/null +++ b/docs/modules/internal/webhook-github-app.md @@ -0,0 +1 @@ +--8<-- "modules/webhook-github-app/README.md" diff --git a/docs/modules/internal/webhook.md b/docs/modules/internal/webhook.md new file mode 100644 index 0000000000..98e6f71e54 --- /dev/null +++ b/docs/modules/internal/webhook.md @@ -0,0 +1 @@ +--8<-- "modules/webhook/README.md" diff --git a/docs/modules/public/ami-housekeeper.md b/docs/modules/public/ami-housekeeper.md new file mode 100644 index 0000000000..dddbd35484 --- /dev/null +++ b/docs/modules/public/ami-housekeeper.md @@ -0,0 +1 @@ +--8<-- "modules/ami-housekeeper/README.md" diff --git a/docs/modules/public/download-lambda.md b/docs/modules/public/download-lambda.md new file mode 100644 index 0000000000..9b85bad769 --- /dev/null +++ b/docs/modules/public/download-lambda.md @@ -0,0 +1 @@ +--8<-- "modules/download-lambda/README.md" diff --git a/docs/modules/public/multi-runner.md b/docs/modules/public/multi-runner.md new file mode 100644 index 0000000000..ebe0e1f309 --- /dev/null +++ b/docs/modules/public/multi-runner.md @@ -0,0 +1 @@ +--8<-- "modules/multi-runner/README.md" diff --git a/docs/modules/public/setup-iam-permissions.md b/docs/modules/public/setup-iam-permissions.md new file mode 100644 index 0000000000..a1e4990fb1 --- /dev/null +++ b/docs/modules/public/setup-iam-permissions.md @@ -0,0 +1 @@ +--8<-- "modules/setup-iam-permissions/README.md" diff --git a/docs/modules/runners.md b/docs/modules/runners.md new file mode 100644 index 0000000000..4059305859 --- /dev/null +++ b/docs/modules/runners.md @@ -0,0 +1,5 @@ +# Runner module (root) + +This module creates resources in your AWS infrastructure, and EC2 instances for hosting the self-hosted runners on-demand. IAM permissions are set to a minimal level, and could be further limited by using permission boundaries. Instances permissions are limited to retrieve and delete the registration token, access the instance's own tags, and terminate the instance itself. By nature instances are short-lived, we strongly suggest to use ephemeral runners to ensure a safe build environment for each workflow job execution. + +--8<-- "README.md:mkdocsrunners" diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 0000000000..4d60bc4431 --- /dev/null +++ b/docs/security.md @@ -0,0 +1,10 @@ + +# Security + +This module creates resources in your AWS infrastructure, and EC2 instances for hosting the self-hosted runners on-demand. IAM permissions are set to a minimal level, and could be further limited by using permission boundaries. Instances permissions are limited to retrieve and delete the registration token, access the instance's own tags, and terminate the instance itself. By nature instances are short-lived, we strongly suggest to use ephemeral runners to ensure a safe build environment for each workflow job execution. + +Ephemeral runners are using the JIT configuration, confguration that only can be used once to activate a runner. For non-ephemeral runners this option is not provided by GitHub. For non-ephemeeral runners a registration token is passed via SSM. After using the token, the token is deleted. But the token remains valid and is potential available in memory on the runner. For ephemeral runners this problem is avoid by using just in time tokens. + +The examples are using standard AMI's for different operation systems. Instances are not hardened, and sudo operation are not blocked. To provide an out of the box working experience by default the module installs and configures the runner. However secrets are not hard coded, they finally end up in the memory of the instances. You can harden the instance by providing your own AMI and overwriting the cloud-init script. + +We welcome any improvement to the standard module to make the default as secure as possible, in the end it remains your responsibility to keep your environment secure. diff --git a/docs/test-lambda-local.md b/docs/test-lambda-local.md deleted file mode 100644 index 86a8a84da4..0000000000 --- a/docs/test-lambda-local.md +++ /dev/null @@ -1,88 +0,0 @@ -# Lambda - Test locally - -This README provides guidance for testing the lambda locally / and or in AWS. This guide assumes you are familiar with AWS, lambda and Node. If not mentioned explicitly, comments provided should be executed from the root of the lambda package. - -## Testing in AWS - -Just navigate to the Lambda in the AWS Console and trigger a test event. Provide an event that matches the required input. For lambdas that does not require a specific event, just send any event. - - -## Testing locally - -Testing locally can be done in two ways; using AWS SAM framework or run via a wrapper to simulate the event to invoke the lambda. Both setups require that the mandatory input environment variables be set, and AWS resources on which the lambda depends are available. We advise for testing the lambda locally to first create your own deployment of the whole module to AWS, this will simplify the setup of dependent AWS resources. For example, based on the de [default example](../../../../examples/default/). - -Local test setup instructions are available for the following lambda's: - -- [runner-binary-syncer](./moduele/../../modules/runner-binaries-syncer/lambdas/runner-binaries-syncer) - This lambda does not need any input, no event is required. Supported via SAM and local Node. - -### Extend deployment configuration - -Add the code below to your Terraform deployment to allow your principal to use the Lambda role and retrieve the lambda configuration. Update your Terraform deployment and apply the changes. - -```hcl -data "aws_caller_identity" "current" {} - -module "runners" { - - ... - - # Assume you have a profile with Admin privileges, allow you to switch to the Lambda role - lambda_principals = [{ - type = "AWS" - identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] - }] - -} - -output "development" { - value = { - lambda_syncer = module.runners.binaries_syncer.lambda - } -} -``` - -Once you have updated your Terraform deployment you need to read the lambda configuration into your environment. Run the commands below in your Terraform workspace folder. - -```bash -LAMBDA_ENV=$(terraform output -json development | jq -r '.lambda_syncer.environment[].variables' | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") -for x in $LAMBDA_ENV ; do echo setting $x; export $x; done -``` - -### Testing with SAM - -This setup requires AWS SAM CLI and Docker is installed locally. First update the AWS config (`~/.aws/config`) so you can use easily switch to the role used by the lambda. - -```properties -[profile gh-development] -source_profile= -region= -role_arn= -``` - -Now you can set the profile and region as environment variables or pass as argument to SAM. - -```bash -export AWS_REGION= -export AWS_PROFILE=gh-development -``` - -For SAM a `template.yml` defines the lambda for running locally. Thats all, now build your lambda with `yarn run dist` and then invoke the lambda with `sam local invoke`. - - -### With Node - -Instead of using SAM you can use Node with `ts-node-dev` to test the code locally. The drawback is that you have to setup AWS credentials in your shell. Also, you are dependent on a tiny wrapper (`local.ts`), and your local Node version. - -The AWS SDK does not seem to handle environment variables for profiles, the only option to pass the role is via credentials. You can get credentials via STS for the role. - -```bash -role=$(aws sts assume-role \ - --role-arn "" \ - --duration-seconds 3600 --role-session-name "dev") - -export AWS_ACCESS_KEY_ID=$(echo $role | jq -r .Credentials.AccessKeyId) -export AWS_SECRET_ACCESS_KEY=$(echo $role | jq -r .Credentials.SecretAccessKey) -export AWS_SESSION_TOKEN=$(echo $role | jq -r .Credentials.SessionToken) -``` - -Next set the region `export AWS_REGION=`. Now you can run the lambda locally via `yarn run watch`. \ No newline at end of file diff --git a/examples/arm64/.terraform.lock.hcl b/examples/arm64/.terraform.lock.hcl index fc8ded5056..60a47db0b8 100644 --- a/examples/arm64/.terraform.lock.hcl +++ b/examples/arm64/.terraform.lock.hcl @@ -2,59 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.15.1" - constraints = "~> 4.0, ~> 4.15" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:KNkM4pOCRzbjlGoCxt4Yl4qGUESLQ2uKIOSHb+aiMlY=", - "zh:1d944144f8d613b8090c0c8391e4b205ca036086d70aceb4cdf664856fa8410c", - "zh:2a0ca16a6b12c0ac509f64512f80bd2ed6e7ea0ec369212efd4be3fa65e9773d", - "zh:3f9efdce4f1c320ffd061e8715e1d031deac1be0b959eaa60c25a274925653e4", - "zh:4cf82f3267b0c3e08be29b0345f711ab84ea1ea75f0e8ce81f5a2fe635ba67b4", - "zh:58474a0b7da438e1bcd53e87f10e28830836ff9b46cce5f09413c90952ae4f78", - "zh:6eb1be8afb0314b6b8424fe212b13beeb04f3f24692f0f3ee86c5153c7eb2e63", - "zh:8022da7d3b050d452ce6c679844e13729bdb4e1b3e75dcf68931af17a06b9277", - "zh:8e2683d00fff1df43440d6e7c04a2c1eb432c7d5dacff32fe8ce9045bc948fe6", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b0c22d9a306e8ac2de57b5291a3d0a7a2c1713e33b7d076005662451afdc4d29", - "zh:ba6b7d7d91388b636145b133da6b4e32620cdc8046352e2dc8f3f0f81ff5d2e2", - "zh:d38a816eb60f4419d99303136a3bb61a0d2df3ca8a1dce2ced9b99bf23efa9f7", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.3" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:FvRIEgCmAezgZUqb2F+PZ9WnSSnR5zbEM2ZI+GLmbMk=", - "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", - "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", - "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", - "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", - "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", - "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", - "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", - "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", - "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", - "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.2.0" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:NvMyFNHHq65GUNyBGjLuLD4ABA6sTlRebZCIK5OtvFU=", - "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", - "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", - "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", - "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", - "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", - "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", - "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", - "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", - "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", - "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/arm64/README.md b/examples/arm64/README.md index d3ec3bb97a..b7d19bce0d 100644 --- a/examples/arm64/README.md +++ b/examples/arm64/README.md @@ -1,4 +1,4 @@ -# Action runners deployment with ARM64 architecture +# Amazon Linux ARM64 This module shows how to create GitHub action runners using AWS Graviton instances which have ARM64 architecture. Lambda release will be downloaded from GitHub. @@ -9,10 +9,10 @@ Steps for the full setup, such as creating a GitHub app can be found in the root > Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases ```bash -cd lambdas-download +cd ../lambdas-download terraform init -terraform apply -cd .. +terraform apply -var=module_version= +cd - ``` Before running Terraform, ensure the GitHub app is configured. See the [configuration details](https://github.com/philips-labs/terraform-aws-github-runner#usages) for more details. @@ -22,10 +22,53 @@ terraform init terraform apply ``` -You can receive the webhook details by running: +The example will try to update the webhook of your GitHub. In case the update fails the apply will not fail. You can receive the webhook details by running: ```bash terraform output -raw webhook_secret ``` -Be-aware some shells will print some end of line character `%`. + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [github\_app](#input\_github\_app) | GitHub App for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [runners](#output\_runners) | n/a | +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/arm64/lambdas-download/README.md b/examples/arm64/lambdas-download/README.md new file mode 100644 index 0000000000..a9a0b890e9 --- /dev/null +++ b/examples/arm64/lambdas-download/README.md @@ -0,0 +1,31 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [lambdas](#module\_lambdas) | ../../../modules/download-lambda | n/a | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [files](#output\_files) | n/a | + \ No newline at end of file diff --git a/examples/arm64/lambdas-download/versions.tf b/examples/arm64/lambdas-download/versions.tf new file mode 100644 index 0000000000..c934712b56 --- /dev/null +++ b/examples/arm64/lambdas-download/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1" +} diff --git a/examples/arm64/main.tf b/examples/arm64/main.tf index c541177cd4..e7b0a2f349 100644 --- a/examples/arm64/main.tf +++ b/examples/arm64/main.tf @@ -12,12 +12,20 @@ resource "random_id" "random" { ### Hybrid account ################################################################################ +module "base" { + source = "../base" + + prefix = local.environment + aws_region = local.aws_region +} + + module "runners" { source = "../../" create_service_linked_role_spot = true aws_region = local.aws_region - vpc_id = module.vpc.vpc_id - subnet_ids = module.vpc.private_subnets + vpc_id = module.base.vpc.vpc_id + subnet_ids = module.base.vpc.private_subnets prefix = local.environment tags = { @@ -25,19 +33,19 @@ module "runners" { } github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } # Grab zip files via lambda_download, will automatically get the ARM64 build - webhook_lambda_zip = "lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "lambdas-download/runners.zip" + webhook_lambda_zip = "../lambdas-download/webhook.zip" + runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + runners_lambda_zip = "../lambdas-download/runners.zip" enable_organization_runners = false # Runners will automatically get the "arm64" label - runner_extra_labels = "default,example" + runner_extra_labels = ["default", "example"] # enable access to the runners via SSM enable_ssm_on_runners = true @@ -51,6 +59,9 @@ module "runners" { # } # } + # enable S3 versioning for runners S3 bucket + # runner_binaries_s3_versioning = "Enabled" + # Uncommet idle config to have idle runners from 9 to 5 in time zone Amsterdam # idle_config = [{ # cron = "* * 9-17 * * *" @@ -70,8 +81,19 @@ module "runners" { runners_maximum_count = 1 # set up a fifo queue to remain order - fifo_build_queue = true + enable_fifo_build_queue = true # override scaling down scale_down_schedule_expression = "cron(* * * * ? *)" } + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint +} diff --git a/examples/arm64/variables.tf b/examples/arm64/variables.tf index 69dcd0c61c..35a65dbd4a 100644 --- a/examples/arm64/variables.tf +++ b/examples/arm64/variables.tf @@ -1,4 +1,8 @@ +variable "github_app" { + description = "GitHub App for API usages." -variable "github_app_key_base64" {} - -variable "github_app_id" {} + type = object({ + id = string + key_base64 = string + }) +} diff --git a/examples/arm64/versions.tf b/examples/arm64/versions.tf index 750fd6c978..349e8243a5 100644 --- a/examples/arm64/versions.tf +++ b/examples/arm64/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 0.14" + required_version = ">= 1.3.0" } diff --git a/examples/arm64/vpc.tf b/examples/arm64/vpc.tf deleted file mode 100644 index a7d21422f1..0000000000 --- a/examples/arm64/vpc.tf +++ /dev/null @@ -1,7 +0,0 @@ -module "vpc" { - source = "git::https://github.com/philips-software/terraform-aws-vpc.git?ref=2.2.0" - - environment = local.environment - aws_region = local.aws_region - create_private_hosted_zone = false -} diff --git a/examples/base/.terraform.lock.hcl b/examples/base/.terraform.lock.hcl new file mode 100644 index 0000000000..2cee4d651f --- /dev/null +++ b/examples/base/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" + hashes = [ + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", + ] +} diff --git a/examples/base/README.md b/examples/base/README.md new file mode 100644 index 0000000000..96ca2a857b --- /dev/null +++ b/examples/base/README.md @@ -0,0 +1,39 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.31.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | 5.0.0 | + +## Resources + +| Name | Type | +|------|------| +| [aws_resourcegroups_group.resourcegroups_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/resourcegroups_group) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_region](#input\_aws\_region) | AWS region to create the VPC, assuming zones `a` and `b` exists. | `string` | n/a | yes | +| [prefix](#input\_prefix) | Prefix used for resource naming. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [vpc](#output\_vpc) | n/a | + diff --git a/examples/base/versions.tf b/examples/base/versions.tf new file mode 100644 index 0000000000..2685117f32 --- /dev/null +++ b/examples/base/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.27" + } + } + required_version = ">= 1" +} diff --git a/examples/base/vpc.tf b/examples/base/vpc.tf index 2e898a77f0..cc6a3b7649 100644 --- a/examples/base/vpc.tf +++ b/examples/base/vpc.tf @@ -1,6 +1,6 @@ module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "3.16.0" + version = "5.0.0" name = "${var.prefix}-vpc" cidr = "10.0.0.0/16" diff --git a/examples/default/.terraform.lock.hcl b/examples/default/.terraform.lock.hcl index 04f4b49cbf..60a47db0b8 100644 --- a/examples/default/.terraform.lock.hcl +++ b/examples/default/.terraform.lock.hcl @@ -2,59 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.15.1" - constraints = ">= 3.63.0, ~> 4.0" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:KNkM4pOCRzbjlGoCxt4Yl4qGUESLQ2uKIOSHb+aiMlY=", - "zh:1d944144f8d613b8090c0c8391e4b205ca036086d70aceb4cdf664856fa8410c", - "zh:2a0ca16a6b12c0ac509f64512f80bd2ed6e7ea0ec369212efd4be3fa65e9773d", - "zh:3f9efdce4f1c320ffd061e8715e1d031deac1be0b959eaa60c25a274925653e4", - "zh:4cf82f3267b0c3e08be29b0345f711ab84ea1ea75f0e8ce81f5a2fe635ba67b4", - "zh:58474a0b7da438e1bcd53e87f10e28830836ff9b46cce5f09413c90952ae4f78", - "zh:6eb1be8afb0314b6b8424fe212b13beeb04f3f24692f0f3ee86c5153c7eb2e63", - "zh:8022da7d3b050d452ce6c679844e13729bdb4e1b3e75dcf68931af17a06b9277", - "zh:8e2683d00fff1df43440d6e7c04a2c1eb432c7d5dacff32fe8ce9045bc948fe6", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b0c22d9a306e8ac2de57b5291a3d0a7a2c1713e33b7d076005662451afdc4d29", - "zh:ba6b7d7d91388b636145b133da6b4e32620cdc8046352e2dc8f3f0f81ff5d2e2", - "zh:d38a816eb60f4419d99303136a3bb61a0d2df3ca8a1dce2ced9b99bf23efa9f7", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.3" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:FvRIEgCmAezgZUqb2F+PZ9WnSSnR5zbEM2ZI+GLmbMk=", - "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", - "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", - "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", - "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", - "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", - "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", - "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", - "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", - "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", - "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.2.0" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:NvMyFNHHq65GUNyBGjLuLD4ABA6sTlRebZCIK5OtvFU=", - "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", - "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", - "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", - "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", - "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", - "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", - "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", - "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", - "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", - "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/default/README.md b/examples/default/README.md index 9cf612ce17..ea50d634a0 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -1,31 +1,76 @@ -# Action runners deployment default example +# Amazon Linux X64 (default) This module shows how to create GitHub action runners. Lambda release will be downloaded from GitHub. ## Usages -Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. +Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](https://github.com/philips-labs/terraform-aws-github-runner). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. -> Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases +> The default example assumes local built lambda's available. Ensure you have built the lambda's. Alternativly you can downlowd the lambda's. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases ```bash -cd lambdas-download +cd ../lambdas-download terraform init -terraform apply -cd .. +terraform apply -var=module_version= +cd - ``` -Before running Terraform, ensure the GitHub app is configured. See the [configuration details](../../README.md#usages) for more details. +Before running Terraform, ensure the GitHub app is configured. See the [configuration details](https://github.com/philips-labs/terraform-aws-github-runner#usages) for more details. ```bash terraform init terraform apply ``` -You can receive the webhook details by running: +The example will try to update the webhook of your GitHub. In case the update fails the apply will not fail. You can receive the webhook details by running: ```bash terraform output -raw webhook_secret ``` -Be-aware some shells will print some end of line character `%`. \ No newline at end of file + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [runners](#output\_runners) | n/a | +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/default/lambdas-download/main.tf b/examples/default/lambdas-download/main.tf deleted file mode 100644 index 87f31bd8a9..0000000000 --- a/examples/default/lambdas-download/main.tf +++ /dev/null @@ -1,25 +0,0 @@ -locals { - version = "" -} - -module "lambdas" { - source = "../../../modules/download-lambda" - lambdas = [ - { - name = "webhook" - tag = local.version - }, - { - name = "runners" - tag = local.version - }, - { - name = "runner-binaries-syncer" - tag = local.version - } - ] -} - -output "files" { - value = module.lambdas.files -} diff --git a/examples/default/main.tf b/examples/default/main.tf index 321e9fe103..38a2c4f096 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -1,6 +1,6 @@ locals { - environment = "default" - aws_region = "eu-west-1" + environment = var.environment != null ? var.environment : "default" + aws_region = var.aws_region } resource "random_id" "random" { @@ -27,8 +27,8 @@ module "runners" { } github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } @@ -43,12 +43,12 @@ module "runners" { # }] # Grab zip files via lambda_download - webhook_lambda_zip = "lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "lambdas-download/runners.zip" + # webhook_lambda_zip = "../lambdas-download/webhook.zip" + # runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + # runners_lambda_zip = "../lambdas-download/runners.zip" - enable_organization_runners = false - runner_extra_labels = "default,example" + enable_organization_runners = true + runner_extra_labels = ["default", "example"] # enable access to the runners via SSM enable_ssm_on_runners = true @@ -62,6 +62,9 @@ module "runners" { # } # } + # enable S3 versioning for runners S3 bucket + # runner_binaries_s3_versioning = "Enabled" + # Uncommet idle config to have idle runners from 9 to 5 in time zone Amsterdam # idle_config = [{ # cron = "* * 9-17 * * *" @@ -76,13 +79,53 @@ module "runners" { # override delay of events in seconds delay_webhook_event = 5 - runners_maximum_count = 1 + runners_maximum_count = 2 # set up a fifo queue to remain order - fifo_build_queue = true + enable_fifo_build_queue = true # override scaling down scale_down_schedule_expression = "cron(* * * * ? *)" # enable this flag to publish webhook events to workflow job queue # enable_workflow_job_events_queue = true + + enable_user_data_debug_logging_runner = true + + # prefix GitHub runners with the environment name + runner_name_prefix = "${local.environment}_" + + # Enable debug logging for the lambda functions + # log_level = "debug" + + enable_ami_housekeeper = true + ami_housekeeper_cleanup_config = { + ssmParameterNames = ["*/ami-id"] + minimumDaysOld = 10 + amiFilters = [ + { + Name = "name" + Values = ["*al2023*"] + } + ] + } + + instance_termination_watcher = { + enable = true + enable_metric = { + spot_warning = true + } + } + +} + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + depends_on = [module.runners] + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint } diff --git a/examples/default/variables.tf b/examples/default/variables.tf index 69dcd0c61c..8a3bce0854 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -1,4 +1,22 @@ +variable "github_app" { + description = "GitHub for API usages." -variable "github_app_key_base64" {} + type = object({ + id = string + key_base64 = string + }) +} -variable "github_app_id" {} +variable "environment" { + description = "Environment name, used as prefix." + + type = string + default = null +} + +variable "aws_region" { + description = "AWS region." + + type = string + default = "eu-west-1" +} diff --git a/examples/default/versions.tf b/examples/default/versions.tf index 376c182312..349e8243a5 100644 --- a/examples/default/versions.tf +++ b/examples/default/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/examples/ephemeral/.terraform.lock.hcl b/examples/ephemeral/.terraform.lock.hcl index 7556f27ad3..60a47db0b8 100644 --- a/examples/ephemeral/.terraform.lock.hcl +++ b/examples/ephemeral/.terraform.lock.hcl @@ -2,59 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.15.1" - constraints = ">= 3.63.0, ~> 4.0, ~> 4.15" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:KNkM4pOCRzbjlGoCxt4Yl4qGUESLQ2uKIOSHb+aiMlY=", - "zh:1d944144f8d613b8090c0c8391e4b205ca036086d70aceb4cdf664856fa8410c", - "zh:2a0ca16a6b12c0ac509f64512f80bd2ed6e7ea0ec369212efd4be3fa65e9773d", - "zh:3f9efdce4f1c320ffd061e8715e1d031deac1be0b959eaa60c25a274925653e4", - "zh:4cf82f3267b0c3e08be29b0345f711ab84ea1ea75f0e8ce81f5a2fe635ba67b4", - "zh:58474a0b7da438e1bcd53e87f10e28830836ff9b46cce5f09413c90952ae4f78", - "zh:6eb1be8afb0314b6b8424fe212b13beeb04f3f24692f0f3ee86c5153c7eb2e63", - "zh:8022da7d3b050d452ce6c679844e13729bdb4e1b3e75dcf68931af17a06b9277", - "zh:8e2683d00fff1df43440d6e7c04a2c1eb432c7d5dacff32fe8ce9045bc948fe6", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b0c22d9a306e8ac2de57b5291a3d0a7a2c1713e33b7d076005662451afdc4d29", - "zh:ba6b7d7d91388b636145b133da6b4e32620cdc8046352e2dc8f3f0f81ff5d2e2", - "zh:d38a816eb60f4419d99303136a3bb61a0d2df3ca8a1dce2ced9b99bf23efa9f7", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.3" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:FvRIEgCmAezgZUqb2F+PZ9WnSSnR5zbEM2ZI+GLmbMk=", - "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", - "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", - "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", - "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", - "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", - "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", - "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", - "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", - "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", - "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.2.0" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:NvMyFNHHq65GUNyBGjLuLD4ABA6sTlRebZCIK5OtvFU=", - "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", - "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", - "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", - "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", - "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", - "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", - "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", - "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", - "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", - "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/ephemeral/README.md b/examples/ephemeral/README.md index 0eec98561d..2a21c46a4e 100644 --- a/examples/ephemeral/README.md +++ b/examples/ephemeral/README.md @@ -1,9 +1,9 @@ -# Action runners deployment ephemeral example +# Ephemeral Amazon Linux xX64 This example is based on the default setup, but shows how runners can be used with the ephemeral flag enabled. Once enabled, ephemeral runners will be used for one job only. Each job requires a fresh instance. This feature should be used in combination with the `workflow_job` event. See GitHub webhook endpoint configuration(link needed here). It is also suggested to use a pre-build AMI to minimize runner launch times. ## Usages -Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. +Steps for the full setup, such as creating a GitHub app can be found the [docs](https://philips-labs.github.io/terraform-aws-github-runner/getting-started/). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. > Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases @@ -14,17 +14,61 @@ terraform apply cd .. ``` -Before running Terraform, ensure the GitHub app is configured. See the [configuration details](../../README.md#usages) for more details. +Before running Terraform, ensure the GitHub app is configured. See the [configuration details](https://philips-labs.github.io/terraform-aws-github-runner/configuration/#ephemeral-runners) for more details. ```bash terraform init terraform apply ``` -You can receive the webhook details by running: +The module will try to update the GitHub App webhook and secret (only linux/mac). You can receive the webhook details by running: ```bash -terraform output -raw webhook_secret +terraform output webhook_secret ``` -Be-aware some shells will print some end of line character `%`. \ No newline at end of file + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [runners](#output\_runners) | n/a | +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/ephemeral/lambdas-download/main.tf b/examples/ephemeral/lambdas-download/main.tf deleted file mode 100644 index 87f31bd8a9..0000000000 --- a/examples/ephemeral/lambdas-download/main.tf +++ /dev/null @@ -1,25 +0,0 @@ -locals { - version = "" -} - -module "lambdas" { - source = "../../../modules/download-lambda" - lambdas = [ - { - name = "webhook" - tag = local.version - }, - { - name = "runners" - tag = local.version - }, - { - name = "runner-binaries-syncer" - tag = local.version - } - ] -} - -output "files" { - value = module.lambdas.files -} diff --git a/examples/ephemeral/main.tf b/examples/ephemeral/main.tf index 5bd0e97c82..d7d0dacc14 100644 --- a/examples/ephemeral/main.tf +++ b/examples/ephemeral/main.tf @@ -1,5 +1,5 @@ locals { - environment = "ephemeral" + environment = var.environment != null ? var.environment : "ephemeral" aws_region = "eu-west-1" } @@ -7,9 +7,6 @@ resource "random_id" "random" { byte_length = 20 } -data "aws_caller_identity" "current" {} - - module "base" { source = "../base" @@ -30,8 +27,8 @@ module "runners" { } github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } @@ -41,10 +38,7 @@ module "runners" { runners_lambda_zip = "../../lambda_output/runners.zip" enable_organization_runners = true - runner_extra_labels = "default,example" - - # enable workflow labels check - # runner_enable_workflow_job_labels_check = true + runner_extra_labels = ["default", "example"] # enable access to the runners via SSM enable_ssm_on_runners = true @@ -66,22 +60,32 @@ module "runners" { enable_ephemeral_runners = true # # Example of simple pool usages - # pool_runner_owner = "my-org" + # pool_runner_owner = "philips-test-runners" # pool_config = [{ - # size = 20 + # size = 3 # schedule_expression = "cron(* * * * ? *)" # }] # # enable_job_queued_check = true + # tracing_config = { + # mode = "Active" + # capture_error = true + # capture_http_requests = true + # } + + # configure your pre-built AMI - # enabled_userdata = false - # ami_filter = { name = ["github-runner-amzn2-x86_64-*"] } - # ami_owners = [data.aws_caller_identity.current.account_id] + # enable_userdata = false + # ami_filter = { name = ["github-runner-al2023-x86_64-*"], state = ["available"] } + # ami_owners = [data.aws_caller_identity.current.account_id] + + # or use the default AMI + # enable_userdata = true - # Enable logging - log_level = "debug" + # Enable debug logging for the lambda functions + # log_level = "debug" # Setup a dead letter queue, by default scale up lambda will kepp retrying to process event in case of scaling error. # redrive_policy_build_queue = { @@ -90,3 +94,15 @@ module "runners" { # deadLetterTargetArn = null # } } + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + depends_on = [module.runners] + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint +} diff --git a/examples/ephemeral/variables.tf b/examples/ephemeral/variables.tf index 1f4576b1b5..e8596eaf0f 100644 --- a/examples/ephemeral/variables.tf +++ b/examples/ephemeral/variables.tf @@ -1,5 +1,15 @@ +variable "github_app" { + description = "GitHub for API usages." -variable "github_app_key_base64" {} + type = object({ + id = string + key_base64 = string + }) +} -variable "github_app_id" {} +variable "environment" { + description = "Environment name, used as prefix" + type = string + default = null +} diff --git a/examples/ephemeral/versions.tf b/examples/ephemeral/versions.tf index 376c182312..349e8243a5 100644 --- a/examples/ephemeral/versions.tf +++ b/examples/ephemeral/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/examples/lambdas-download/.terraform.lock.hcl b/examples/lambdas-download/.terraform.lock.hcl new file mode 100644 index 0000000000..da897cd060 --- /dev/null +++ b/examples/lambdas-download/.terraform.lock.hcl @@ -0,0 +1,45 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.31.0" + constraints = "~> 5.27" + hashes = [ + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", + ] +} diff --git a/examples/lambdas-download/README.md b/examples/lambdas-download/README.md new file mode 100644 index 0000000000..93ace73e95 --- /dev/null +++ b/examples/lambdas-download/README.md @@ -0,0 +1,42 @@ +# Wrapper module to download lambda's for running the examples + +Module is used by examples to download Lambda distribution from the GitHub release. + +```bash +terraform init +terraform apply -var=module_version= +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [lambdas](#module\_lambdas) | ../../modules/download-lambda | n/a | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [module\_version](#input\_module\_version) | Module release version. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [files](#output\_files) | n/a | + \ No newline at end of file diff --git a/examples/lambdas-download/main.tf b/examples/lambdas-download/main.tf new file mode 100644 index 0000000000..d28bc519e6 --- /dev/null +++ b/examples/lambdas-download/main.tf @@ -0,0 +1,29 @@ +module "lambdas" { + source = "../../modules/download-lambda" + lambdas = [ + { + name = "webhook" + tag = var.module_version + }, + { + name = "runners" + tag = var.module_version + }, + { + name = "runner-binaries-syncer" + tag = var.module_version + }, + { + name = "ami-housekeeper" + tag = var.module_version + }, + { + name = "termination-watcher" + tag = var.module_version + } + ] +} + +output "files" { + value = module.lambdas.files +} diff --git a/examples/lambdas-download/variables.tf b/examples/lambdas-download/variables.tf new file mode 100644 index 0000000000..f5876a9b51 --- /dev/null +++ b/examples/lambdas-download/variables.tf @@ -0,0 +1,4 @@ +variable "module_version" { + description = "Module release version." + type = string +} diff --git a/examples/lambdas-download/versions.tf b/examples/lambdas-download/versions.tf new file mode 100644 index 0000000000..c934712b56 --- /dev/null +++ b/examples/lambdas-download/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1" +} diff --git a/examples/multi-runner/.terraform.lock.hcl b/examples/multi-runner/.terraform.lock.hcl new file mode 100644 index 0000000000..02517c56fd --- /dev/null +++ b/examples/multi-runner/.terraform.lock.hcl @@ -0,0 +1,85 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.39.1" + constraints = ">= 5.0.0, ~> 5.27" + hashes = [ + "h1:V29aKJqUWugn9F2pBIaWLwHLTmgFpirKEv1aNRX1kV4=", + "zh:05c50a5d8edb3ba4ebc4eb6e0d0b5e319142f5983b27821710ed7d475d335bdc", + "zh:082986a5784dd21957e632371b289e549f051a4ea21d5c78c6d744c3537f03c5", + "zh:192ae622ba562eacc4921ed549a794506179233d724fdd15a4f147f3400724a0", + "zh:19a1d4637a62de90b0da174c0bf01000cd900488f7e8f709d8a37f082c59756b", + "zh:1d7689a8583515f1705972d7ce57ccfab96215b19905530d2c78c02dcfaff583", + "zh:22c446a21209a52ab74b4ba1ede0b220531e97ce479430047e493a2c45e1d8cb", + "zh:4154de82290ab4e9f81bac1ea62342de8b3b7a608f99258c190d4dd1c6663e47", + "zh:6bc4859ccdc54f28af9286b2fa090a31dcb345138d68c471510b737f6a052011", + "zh:73c69e000e0b321e78a4a12fef60d37285f2afec0ea7be9e06163d985101cb59", + "zh:890a3422f5e445b49bae30facf448d0ec9cd647e9155d0b685b5b39e9d331a94", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9cd88bec0f5205df9032e3126d4e57edd1c5cc8d45cda25626882dafc485a3b0", + "zh:a3a8e3276d0fbf051bbafa192a2998b05745f2cf285ac8c36a9ad167a75c037f", + "zh:d47e4dcf4c0ad71b9a7c720be4f3a89f6786a82e77bbe8d950794562792a1da5", + "zh:f74e5b2af508c7de80a6ae5198df54a795eeba5058a0cd247828943f0c54f6e0", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.4.1" + constraints = "~> 2.0" + hashes = [ + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.6.0" + constraints = "~> 3.0" + hashes = [ + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", + ] +} diff --git a/examples/multi-runner/README.md b/examples/multi-runner/README.md new file mode 100644 index 0000000000..8554821658 --- /dev/null +++ b/examples/multi-runner/README.md @@ -0,0 +1,93 @@ +# Action runners deployment of Multiple-Runner-Configurations-Together example + +This module shows how to create GitHub action runners with multiple runner configuration together in one deployment. This example has the configurations for the following runner types with the relevant labels supported by them as matchers: + +- Linux ARM64 `["self-hosted", "linux", "arm64", "amazon"]` +- Linux Ubuntu `["self-hosted", "linux", "x64", "ubuntu-latest"]` or `["self-hosted", "linux", "x64", "ubuntu-2204"]` +- Linux X64 `["self-hosted", "linux", "x64", "amazon"]` +- Windows X64 `["self-hosted", "windows", "x64", "servercore-2022"]` + +The module will decide the runner for the workflow job based on the match in the labels defined in the workflow job and runner configuration. Also the runner configuration allows the match to be exact or non-exact match. We recommend to use only exact matches. + +For exact match, all the labels defined in the workflow should be present in the runner configuration matchers and for non-exact match, some of the labels in the workflow, when present in runner configuration, shall be enough for the runner configuration to be used for the job. First the exact matchers are applied, next the non exact ones. + +## Webhook + +For the list of provided runner configurations, there will be a single webhook and only a single Github App to receive the notifications for all types of workflow triggers. + +## Lambda distribution + +Per combination of OS and architecture a lambda distribution syncer will be created. For this example there will be three instances (windows X64, linux X64, linux ARM). + +## Usages + +Steps for the full setup, such as creating a GitHub app can be found the [docs](https://philips-labs.github.io/terraform-aws-github-runner/). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. + +> The default example assumes local built lambda's available. Ensure you have built the lambda's. Alternativly you can downlowd the lambda's. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases + +```bash +cd ../lambdas-download +terraform init +terraform apply -var=module_version= +cd - +``` + + +Before running Terraform, ensure the GitHub app is configured. See the [configuration details](https://philips-labs.github.io/terraform-aws-github-runner/configuration/) for more details. + +```bash +terraform init +terraform apply +``` + +The example will try to update the webhook of your GitHub. In case the update fails the apply will not fail. You can receive the webhook details by running: + +```bash +terraform output -raw webhook_secret +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../modules/multi-runner | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_region](#input\_aws\_region) | AWS region to deploy to | `string` | `"eu-west-1"` | no | +| [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/multi-runner/main.tf b/examples/multi-runner/main.tf new file mode 100644 index 0000000000..0563831d26 --- /dev/null +++ b/examples/multi-runner/main.tf @@ -0,0 +1,122 @@ +locals { + environment = var.environment != null ? var.environment : "multi-runner" + aws_region = var.aws_region + + # Load runner configurations from Yaml files + multi_runner_config_files = { + for c in fileset("${path.module}/templates/runner-configs", "*.yaml") : + + trimsuffix(c, ".yaml") => yamldecode(file("${path.module}/templates/runner-configs/${c}")) + } + multi_runner_config = { + for k, v in local.multi_runner_config_files : + + k => merge( + v, + { + runner_config = merge( + v.runner_config, + { + subnet_ids = lookup(v.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null + vpc_id = lookup(v.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null + } + ) + } + ) + } +} + +resource "random_id" "random" { + byte_length = 20 +} + +module "base" { + source = "../base" + + prefix = local.environment + aws_region = local.aws_region +} + +module "runners" { + source = "../../modules/multi-runner" + multi_runner_config = local.multi_runner_config + # Alternative to loading runner configuration from Yaml files is using static configuration: + # multi_runner_config = { + # "linux-x64" = { + # matcherConfig : { + # labelMatchers = [["self-hosted", "linux", "x64", "amazon"]] + # exactMatch = false + # } + # fifo = true + # delay_webhook_event = 0 + # runner_config = { + # runner_os = "linux" + # runner_architecture = "x64" + # runner_name_prefix = "amazon-x64_" + # create_service_linked_role_spot = true + # enable_ssm_on_runners = true + # instance_types = ["m5ad.large", "m5a.large"] + # runner_extra_labels = ["amazon"] + # runners_maximum_count = 1 + # enable_ephemeral_runners = true + # scale_down_schedule_expression = "cron(* * * * ? *)" + # } + # } + # } + aws_region = local.aws_region + vpc_id = module.base.vpc.vpc_id + subnet_ids = module.base.vpc.private_subnets + runners_scale_up_lambda_timeout = 60 + runners_scale_down_lambda_timeout = 60 + prefix = local.environment + tags = { + Project = "ProjectX" + } + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + # enable this section for tracing + # tracing_config = { + # mode = "Active" + # capture_error = true + # capture_http_requests = true + # } + # Assuming local build lambda's to use pre build ones, uncomment the lines below and download the + # lambda zip files lambda_download + # webhook_lambda_zip = "../lambdas-download/webhook.zip" + # runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + # runners_lambda_zip = "../lambdas-download/runners.zip" + + # enable_workflow_job_events_queue = true + # override delay of events in seconds + + # Enable debug logging for the lambda functions + # log_level = "debug" + + # Enable spot termination watcher + # spot_instance_termination_watcher = { + # enable = true + # } + + # Enable to track the spot instance termination warning + # instance_termination_watcher = { + # enable = true + # enable_metric = { + # spot_warning = true + # } + # } +} + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + depends_on = [module.runners] + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint +} diff --git a/examples/multi-runner/outputs.tf b/examples/multi-runner/outputs.tf new file mode 100644 index 0000000000..1feaf2e671 --- /dev/null +++ b/examples/multi-runner/outputs.tf @@ -0,0 +1,8 @@ +output "webhook_endpoint" { + value = module.runners.webhook.endpoint +} + +output "webhook_secret" { + sensitive = true + value = random_id.random.hex +} diff --git a/examples/multi-runner/providers.tf b/examples/multi-runner/providers.tf new file mode 100644 index 0000000000..eca2fe96a7 --- /dev/null +++ b/examples/multi-runner/providers.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = local.aws_region + + default_tags { + tags = { + Example = local.environment + } + } +} diff --git a/examples/multi-runner/templates/runner-configs/linux-arm64.yaml b/examples/multi-runner/templates/runner-configs/linux-arm64.yaml new file mode 100644 index 0000000000..7cfe859242 --- /dev/null +++ b/examples/multi-runner/templates/runner-configs/linux-arm64.yaml @@ -0,0 +1,20 @@ +matcherConfig: + exactMatch: true + labelMatchers: + - [self-hosted, linux, arm64, amazon] +fifo: true +redrive_build_queue: + enabled: false + maxReceiveCount: null +runner_config: + runner_os: linux + runner_architecture: arm64 + runner_name_prefix: amazon-arm64_ + enable_ssm_on_runners: true + credit_specification: unlimited + instance_types: + - t4g.large + - c6g.large + runners_maximum_count: 1 + delay_webhook_event: 0 + scale_down_schedule_expression: cron(* * * * ? *) diff --git a/examples/multi-runner/templates/runner-configs/linux-x64-ubuntu.yaml b/examples/multi-runner/templates/runner-configs/linux-x64-ubuntu.yaml new file mode 100644 index 0000000000..4b555d194c --- /dev/null +++ b/examples/multi-runner/templates/runner-configs/linux-x64-ubuntu.yaml @@ -0,0 +1,54 @@ +matcherConfig: + exactMatch: true + labelMatchers: + - [self-hosted, linux, x64, ubuntu-latest] + - [self-hosted, linux, x64, ubuntu-2204] +fifo: true +redrive_build_queue: + enabled: false + maxReceiveCount: null +runner_config: + runner_os: linux + runner_architecture: x64 + runner_run_as: ubuntu + runner_name_prefix: ubuntu-2204-x64_ + enable_ssm_on_runners: true + credit_specification: standard + instance_types: + - t3a.large + - m5ad.large + - m5a.large + runners_maximum_count: 1 + delay_webhook_event: 0 + scale_down_schedule_expression: cron(* * * * ? *) + userdata_template: ./templates/user-data.sh + ami_owners: + - "099720109477" # Canonical's Amazon account ID + ami_filter: + name: + - ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-* + state: + - available + block_device_mappings: + - device_name: /dev/sda1 + delete_on_termination: true + volume_type: gp3 + volume_size: 30 + encrypted: true + iops: null + throughput: null + kms_key_id: null + snapshot_id: null + runner_log_files: + - log_group_name: syslog + prefix_log_group: true + file_path: /var/log/syslog + log_stream_name: "{instance_id}" + - log_group_name: user_data + prefix_log_group: true + file_path: /var/log/user-data.log + log_stream_name: "{instance_id}/user_data" + - log_group_name: runner + prefix_log_group: true + file_path: /opt/actions-runner/_diag/Runner_**.log + log_stream_name: "{instance_id}/runner" diff --git a/examples/multi-runner/templates/runner-configs/linux-x64.yaml b/examples/multi-runner/templates/runner-configs/linux-x64.yaml new file mode 100644 index 0000000000..84d9aa650e --- /dev/null +++ b/examples/multi-runner/templates/runner-configs/linux-x64.yaml @@ -0,0 +1,27 @@ +matcherConfig: + exactMatch: false + labelMatchers: + - [ self-hosted, linux, x64, amazon ] + priority: 1 # set ephemeral runner priority to 1 +fifo: true +runner_config: + runner_os: linux + runner_architecture: x64 + runner_name_prefix: amazon-x64_ + enable_ssm_on_runners: true + vpc_id: ${vpc_id} + subnet_ids: ${subnet_ids} + instance_types: + - m5ad.large + - m5a.large + runners_maximum_count: 1 + enable_ephemeral_runners: true + enable_on_demand_failover_for_errors: ['InsufficientInstanceCapacity'] + create_service_linked_role_spot: true + delay_webhook_event: 0 + scale_down_schedule_expression: cron(* * * * ? *) + runner_metadata_options: + instance_metadata_tags: disabled + http_endpoint: enabled + http_tokens: optional + http_put_response_hop_limit: 1 diff --git a/examples/multi-runner/templates/runner-configs/windows-x64.yaml b/examples/multi-runner/templates/runner-configs/windows-x64.yaml new file mode 100644 index 0000000000..fdf8be6533 --- /dev/null +++ b/examples/multi-runner/templates/runner-configs/windows-x64.yaml @@ -0,0 +1,22 @@ +matcherConfig: + exactMatch: true + labelMatchers: + - [self-hosted, windows, x64, servercore-2022] +fifo: true +runner_config: + runner_os: windows + runner_architecture: x64 + runner_name_prefix: servercore-2022-x64_ + enable_ssm_on_runners: true + instance_types: + - m5.large + - c5.large + runners_maximum_count: 1 + delay_webhook_event: 5 + scale_down_schedule_expression: cron(* * * * ? *) + runner_boot_time_in_minutes: 20 + ami_filter: + name: + - Windows_Server-2022-English-Full-ECS_Optimized-* + state: + - available diff --git a/examples/multi-runner/templates/user-data.sh b/examples/multi-runner/templates/user-data.sh new file mode 100644 index 0000000000..752a0de0e3 --- /dev/null +++ b/examples/multi-runner/templates/user-data.sh @@ -0,0 +1,84 @@ +#!/bin/bash +exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1 + + +# AWS suggest to create a log for debug purpose based on https://aws.amazon.com/premiumsupport/knowledge-center/ec2-linux-log-user-data/ +# As side effect all command, set +x disable debugging explicitly. +# +# An alternative for masking tokens could be: exec > >(sed 's/--token\ [^ ]* /--token\ *** /g' > /var/log/user-data.log) 2>&1 +set +x + +%{ if enable_debug_logging } +set -x +%{ endif } + +${pre_install} + +# Install AWS CLI +apt-get update +DEBIAN_FRONTEND=noninteractive apt-get install -y \ + awscli \ + build-essential \ + curl \ + git \ + iptables \ + jq \ + uidmap \ + unzip \ + wget + +user_name=ubuntu +user_id=$(id -ru $user_name) + +# install and configure cloudwatch logging agent +wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb +dpkg -i -E ./amazon-cloudwatch-agent.deb +amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c ssm:${ssm_key_cloudwatch_agent_config} + +# configure systemd for running service in users accounts +cat >/etc/systemd/user@UID.service <<-EOF + +[Unit] +Description=User Manager for UID %i +After=user-runtime-dir@%i.service +Wants=user-runtime-dir@%i.service + +[Service] +LimitNOFILE=infinity +LimitNPROC=infinity +User=%i +PAMName=systemd-user +Type=notify + +[Install] +WantedBy=default.target + +EOF + +echo export XDG_RUNTIME_DIR=/run/user/$user_id >>/home/$user_name/.bashrc + +systemctl daemon-reload +systemctl enable user@UID.service +systemctl start user@UID.service + +curl -fsSL https://get.docker.com/rootless >>/opt/rootless.sh && chmod 755 /opt/rootless.sh +su -l $user_name -c /opt/rootless.sh +echo export DOCKER_HOST=unix:///run/user/$user_id/docker.sock >>/home/$user_name/.bashrc +echo export PATH=/home/$user_name/bin:$PATH >>/home/$user_name/.bashrc + +# Run docker service by default +loginctl enable-linger $user_name +su -l $user_name -c "systemctl --user enable docker" + +${install_runner} + +# config runner for rootless docker +cd /opt/actions-runner/ +echo DOCKER_HOST=unix:///run/user/$user_id/docker.sock >>.env +echo PATH=/home/$user_name/bin:$PATH >>.env + +${post_install} + +cd /opt/actions-runner + +${start_runner} diff --git a/examples/multi-runner/variables.tf b/examples/multi-runner/variables.tf new file mode 100644 index 0000000000..009c3643db --- /dev/null +++ b/examples/multi-runner/variables.tf @@ -0,0 +1,22 @@ +variable "github_app" { + description = "GitHub for API usages." + + type = object({ + id = string + key_base64 = string + }) +} + +variable "environment" { + description = "Environment name, used as prefix" + + type = string + default = null +} + +variable "aws_region" { + description = "AWS region to deploy to" + + type = string + default = "eu-west-1" +} diff --git a/examples/multi-runner/versions.tf b/examples/multi-runner/versions.tf new file mode 100644 index 0000000000..349e8243a5 --- /dev/null +++ b/examples/multi-runner/versions.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.27" + } + local = { + source = "hashicorp/local" + version = "~> 2.0" + } + random = { + source = "hashicorp/random" + version = "~> 3.0" + } + } + required_version = ">= 1.3.0" +} diff --git a/examples/permissions-boundary/.terraform.lock.hcl b/examples/permissions-boundary/.terraform.lock.hcl index 7ca28893c6..f5f3c3a23c 100644 --- a/examples/permissions-boundary/.terraform.lock.hcl +++ b/examples/permissions-boundary/.terraform.lock.hcl @@ -2,59 +2,64 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.12.1" - constraints = ">= 3.63.0, ~> 4.0" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:YvwxXRDVzn9j6Gt7Vg8tCcyF/niapue5sxSUw1TH+9U=", - "zh:2b432dc3bf7e0987bf9dcad5d397c384890d12fcd95827bc4581ca2955fc623a", - "zh:2f79a448a4e5ad24a706ab634078d0ef159be3278eb24988b7d2185173f5dd8f", - "zh:5d70074c10cefb30d4104af54f912e58ffa1b6871277b0a5324c8f13000f5009", - "zh:63623743fb15d54787a96c9761b97a935ff396672e625730cb7a5c1971acf4b6", - "zh:8263f376e6db684667c10e28df8d8d188e02fd09ad58e1ad7075e363c389e24c", - "zh:8b5aa9fd1ddf1de0ab7d462891123405e5af04d7e4d1e4b03381634b3cae4884", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:d00b2d0b374ab92e934eb597668c5f3e415c4cf8335e6a52ab99949b8fcf57dd", - "zh:d0e037725aced6cacc2e0a1903b31083c64f8765fb1263e4f8f891745266b7fb", - "zh:e6e244123bc1df109db90bef0af2a875a0b3afb268f21c3e5bc34753657102ad", - "zh:ec6901ab8b99ae3df50340e9aa86ed3bac1369f5e1403c0362edd9944640fa22", - "zh:f6a4d0ce3bd3d4b81163c4ae75b66e50c10b935c60a63d7fb96df285c0eeca40", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.2" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:BVEZnjtpWxKPG9OOQh4dFa1z5pwMO/uuzYtu6AR2LyM=", - "zh:027e4873c69da214e2fed131666d5de92089732a11d096b68257da54d30b6f9d", - "zh:0ba2216e16cfb72538d76a4c4945b4567a76f7edbfef926b1c5a08d7bba2a043", - "zh:1fee8f6aae1833c27caa96e156cf99a681b6f085e476d7e1b77d285e21d182c1", - "zh:2e8a3e72e877003df1c390a231e0d8e827eba9f788606e643f8e061218750360", - "zh:719008f9e262aa1523a6f9132adbe9eee93c648c2981f8359ce41a40e6425433", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9a70fdbe6ef955c4919a4519caca116f34c19c7ddedd77990fbe4f80fe66dc84", - "zh:abc412423d670cbb6264827fa80e1ffdc4a74aff3f19ba6a239dd87b85b15bec", - "zh:ae953a62c94d2a2a0822e5717fafc54e454af57bd6ed02cd301b9786765c1dd3", - "zh:be0910bdf46698560f9e86f51a4ff795c62c02f8dc82b2b1dab77a0b3a93f61e", - "zh:e58f9083b7971919b95f553227adaa7abe864fce976f0166cf4d65fc17257ff2", - "zh:ff4f77cbdbb22cc98182821c7ef84dce16298ab0e997d5c7fae97247f7a4bcb0", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.1.3" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:LPSVX+oXKGaZmxgtaPf2USxoEsWK/pnhmm/5FKw+PtU=", - "zh:26e07aa32e403303fc212a4367b4d67188ac965c37a9812e07acee1470687a73", - "zh:27386f48e9c9d849fbb5a8828d461fde35e71f6b6c9fc235bc4ae8403eb9c92d", - "zh:5f4edda4c94240297bbd9b83618fd362348cadf6bf24ea65ea0e1844d7ccedc0", - "zh:646313a907126cd5e69f6a9fafe816e9154fccdc04541e06fed02bb3a8fa2d2e", - "zh:7349692932a5d462f8dee1500ab60401594dddb94e9aa6bf6c4c0bd53e91bbb8", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:9034daba8d9b32b35930d168f363af04cecb153d5849a7e4a5966c97c5dc956e", - "zh:bb81dfca59ef5f949ef39f19ea4f4de25479907abc28cdaa36d12ecd7c0a9699", - "zh:bcf7806b99b4c248439ae02c8e21f77aff9fadbc019ce619b929eef09d1221bb", - "zh:d708e14d169e61f326535dd08eecd3811cd4942555a6f8efabc37dbff9c6fc61", - "zh:dc294e19a46e1cefb9e557a7b789c8dd8f319beca99b8c265181bc633dc434cc", - "zh:f9d758ee53c55dc016dd736427b6b0c3c8eb4d0dbbc785b6a3579b0ffedd9e42", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/permissions-boundary/README.md b/examples/permissions-boundary/README.md index 60d21345f7..04db107526 100644 --- a/examples/permissions-boundary/README.md +++ b/examples/permissions-boundary/README.md @@ -4,11 +4,6 @@ This module shows how to create GitHub action runners with permissions boundarie ## Usages -Steps for the full setup, such as creating a GitHub app can be find the module [README](../../README.md). First create the deploy role and boundary policies. These steps require an admin user. - -> Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases - - ```bash cd setup terraform init @@ -21,10 +16,10 @@ Now a new role and policies should be created. The output of the previous step i Download the lambda releases. ```bash -cd lambdas-download +cd ../lambdas-download terraform init -terraform apply -cd .. +terraform apply -var=module_version= +cd - ``` Now you can deploy the module. @@ -33,3 +28,51 @@ Now you can deploy the module. terraform init terraform apply ``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.31.0 | +| [random](#provider\_random) | 3.6.0 | +| [terraform](#provider\_terraform) | n/a | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_kms_alias.github](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource | +| [aws_kms_key.github](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [terraform_remote_state.iam](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/data-sources/remote_state) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [runners](#output\_runners) | n/a | +| [webhook](#output\_webhook) | n/a | + diff --git a/examples/permissions-boundary/lambdas-download/main.tf b/examples/permissions-boundary/lambdas-download/main.tf deleted file mode 100644 index 87f31bd8a9..0000000000 --- a/examples/permissions-boundary/lambdas-download/main.tf +++ /dev/null @@ -1,25 +0,0 @@ -locals { - version = "" -} - -module "lambdas" { - source = "../../../modules/download-lambda" - lambdas = [ - { - name = "webhook" - tag = local.version - }, - { - name = "runners" - tag = local.version - }, - { - name = "runner-binaries-syncer" - tag = local.version - } - ] -} - -output "files" { - value = module.lambdas.files -} diff --git a/examples/permissions-boundary/main.tf b/examples/permissions-boundary/main.tf index c4fc4630f3..3b7348ae8c 100644 --- a/examples/permissions-boundary/main.tf +++ b/examples/permissions-boundary/main.tf @@ -23,6 +23,12 @@ resource "aws_kms_alias" "github" { name = "alias/github/action-runners" target_key_id = aws_kms_key.github.key_id } +module "base" { + source = "../base" + + prefix = local.environment + aws_region = local.aws_region +} module "runners" { source = "../../" @@ -31,8 +37,8 @@ module "runners" { } aws_region = local.aws_region - vpc_id = module.vpc.vpc_id - subnet_ids = module.vpc.private_subnets + vpc_id = module.base.vpc.vpc_id + subnet_ids = module.base.vpc.private_subnets kms_key_arn = aws_kms_key.github.key_id prefix = local.environment @@ -41,18 +47,16 @@ module "runners" { } github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id - client_id = var.github_app_client_id - client_secret = var.github_app_client_secret + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } - webhook_lambda_zip = "lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "lambdas-download/runners.zip" + webhook_lambda_zip = "../lambdas-download/webhook.zip" + runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + runners_lambda_zip = "../lambdas-download/runners.zip" enable_organization_runners = false - runner_extra_labels = "default,example" + runner_extra_labels = ["default", "example"] instance_profile_path = "/runners/" role_path = "/runners/" diff --git a/examples/permissions-boundary/setup/.terraform.lock.hcl b/examples/permissions-boundary/setup/.terraform.lock.hcl index d91b98c1c1..9ccf7ef886 100644 --- a/examples/permissions-boundary/setup/.terraform.lock.hcl +++ b/examples/permissions-boundary/setup/.terraform.lock.hcl @@ -2,21 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.12.1" - constraints = "~> 4.0" + version = "5.31.0" + constraints = "~> 5.2" hashes = [ - "h1:YvwxXRDVzn9j6Gt7Vg8tCcyF/niapue5sxSUw1TH+9U=", - "zh:2b432dc3bf7e0987bf9dcad5d397c384890d12fcd95827bc4581ca2955fc623a", - "zh:2f79a448a4e5ad24a706ab634078d0ef159be3278eb24988b7d2185173f5dd8f", - "zh:5d70074c10cefb30d4104af54f912e58ffa1b6871277b0a5324c8f13000f5009", - "zh:63623743fb15d54787a96c9761b97a935ff396672e625730cb7a5c1971acf4b6", - "zh:8263f376e6db684667c10e28df8d8d188e02fd09ad58e1ad7075e363c389e24c", - "zh:8b5aa9fd1ddf1de0ab7d462891123405e5af04d7e4d1e4b03381634b3cae4884", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:d00b2d0b374ab92e934eb597668c5f3e415c4cf8335e6a52ab99949b8fcf57dd", - "zh:d0e037725aced6cacc2e0a1903b31083c64f8765fb1263e4f8f891745266b7fb", - "zh:e6e244123bc1df109db90bef0af2a875a0b3afb268f21c3e5bc34753657102ad", - "zh:ec6901ab8b99ae3df50340e9aa86ed3bac1369f5e1403c0362edd9944640fa22", - "zh:f6a4d0ce3bd3d4b81163c4ae75b66e50c10b935c60a63d7fb96df285c0eeca40", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } diff --git a/examples/permissions-boundary/setup/README.md b/examples/permissions-boundary/setup/README.md new file mode 100644 index 0000000000..0b54340386 --- /dev/null +++ b/examples/permissions-boundary/setup/README.md @@ -0,0 +1,37 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.31.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [iam](#module\_iam) | ../../../modules/setup-iam-permissions | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [boundary](#output\_boundary) | n/a | +| [role](#output\_role) | n/a | + \ No newline at end of file diff --git a/examples/permissions-boundary/setup/main.tf b/examples/permissions-boundary/setup/main.tf index 63fd737a9c..1c91c82fd5 100644 --- a/examples/permissions-boundary/setup/main.tf +++ b/examples/permissions-boundary/setup/main.tf @@ -3,8 +3,7 @@ data "aws_caller_identity" "current" {} module "iam" { source = "../../../modules/setup-iam-permissions" - environment = "boundaries" - account_id = data.aws_caller_identity.current.account_id + account_id = data.aws_caller_identity.current.account_id namespaces = { boundary_namespace = "boundaries" diff --git a/examples/permissions-boundary/setup/versions.tf b/examples/permissions-boundary/setup/versions.tf index ab771c896a..ac6bb23d38 100644 --- a/examples/permissions-boundary/setup/versions.tf +++ b/examples/permissions-boundary/setup/versions.tf @@ -2,8 +2,8 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/examples/permissions-boundary/variables.tf b/examples/permissions-boundary/variables.tf index d2a93c6c71..d8b5356484 100644 --- a/examples/permissions-boundary/variables.tf +++ b/examples/permissions-boundary/variables.tf @@ -1,8 +1,8 @@ - -variable "github_app_key_base64" {} - -variable "github_app_id" {} - -variable "github_app_client_id" {} - -variable "github_app_client_secret" {} +variable "github_app" { + description = "GitHub for API usages." + + type = object({ + id = string + key_base64 = string + }) +} diff --git a/examples/permissions-boundary/versions.tf b/examples/permissions-boundary/versions.tf index 376c182312..349e8243a5 100644 --- a/examples/permissions-boundary/versions.tf +++ b/examples/permissions-boundary/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/examples/permissions-boundary/vpc.tf b/examples/permissions-boundary/vpc.tf deleted file mode 100644 index 6b19a06b3f..0000000000 --- a/examples/permissions-boundary/vpc.tf +++ /dev/null @@ -1,21 +0,0 @@ -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "3.11.2" - - name = "vpc-${local.environment}" - cidr = "10.0.0.0/16" - - azs = ["${local.aws_region}a", "${local.aws_region}b", "${local.aws_region}c"] - private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] - public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] - - enable_dns_hostnames = true - enable_nat_gateway = true - map_public_ip_on_launch = false - single_nat_gateway = true - - tags = { - Environment = local.environment - } - -} diff --git a/examples/prebuilt/.terraform.lock.hcl b/examples/prebuilt/.terraform.lock.hcl index 7556f27ad3..60a47db0b8 100644 --- a/examples/prebuilt/.terraform.lock.hcl +++ b/examples/prebuilt/.terraform.lock.hcl @@ -2,59 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.15.1" - constraints = ">= 3.63.0, ~> 4.0, ~> 4.15" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:KNkM4pOCRzbjlGoCxt4Yl4qGUESLQ2uKIOSHb+aiMlY=", - "zh:1d944144f8d613b8090c0c8391e4b205ca036086d70aceb4cdf664856fa8410c", - "zh:2a0ca16a6b12c0ac509f64512f80bd2ed6e7ea0ec369212efd4be3fa65e9773d", - "zh:3f9efdce4f1c320ffd061e8715e1d031deac1be0b959eaa60c25a274925653e4", - "zh:4cf82f3267b0c3e08be29b0345f711ab84ea1ea75f0e8ce81f5a2fe635ba67b4", - "zh:58474a0b7da438e1bcd53e87f10e28830836ff9b46cce5f09413c90952ae4f78", - "zh:6eb1be8afb0314b6b8424fe212b13beeb04f3f24692f0f3ee86c5153c7eb2e63", - "zh:8022da7d3b050d452ce6c679844e13729bdb4e1b3e75dcf68931af17a06b9277", - "zh:8e2683d00fff1df43440d6e7c04a2c1eb432c7d5dacff32fe8ce9045bc948fe6", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b0c22d9a306e8ac2de57b5291a3d0a7a2c1713e33b7d076005662451afdc4d29", - "zh:ba6b7d7d91388b636145b133da6b4e32620cdc8046352e2dc8f3f0f81ff5d2e2", - "zh:d38a816eb60f4419d99303136a3bb61a0d2df3ca8a1dce2ced9b99bf23efa9f7", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.3" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:FvRIEgCmAezgZUqb2F+PZ9WnSSnR5zbEM2ZI+GLmbMk=", - "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", - "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", - "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", - "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", - "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", - "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", - "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", - "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", - "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", - "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.2.0" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:NvMyFNHHq65GUNyBGjLuLD4ABA6sTlRebZCIK5OtvFU=", - "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", - "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", - "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", - "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", - "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", - "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", - "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", - "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", - "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", - "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/prebuilt/README.md b/examples/prebuilt/README.md index de0addf46f..fe6c6ec283 100644 --- a/examples/prebuilt/README.md +++ b/examples/prebuilt/README.md @@ -1,48 +1,11 @@ -# Action runners deployment with prebuilt image +# Ubuntu custom AMI example This module shows how to create GitHub action runners using a prebuilt AMI for the runners. - Configured to run with org level runners. - GitHub runner binary syncer is not deployed. -## Usages - -Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md). - -## Variables - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [ami\_filter](#input\_ami\_filter) | The amis to search. Use the default for the provided amazon linux image, `github-runner-windows-core-2019-*` for the provided Windows image | `string` | `github-runner-amzn2-x86_64-2021*` | no | -| [github\_app\_key\_base64](#input\_github\_app\_key\_base64) | The base64 encoded private key you downloaded from GitHub when creating the app | `string` | | yes | -| [github\_app\_id](#input\_github\_app\_id) | The id of the app you created on GitHub | `string` | | yes | -| [region](#input\_region) | The target aws region | `string` | `eu-west-1` | no | -| [runner\_os](#input\_runner\_os) | The os of the image, either `linux` or `windows` | `string` | `linux` | no | - -### Lambdas - -You can either download the released lambda code or build them locally yourself. - -First download the Lambda releases from GitHub. Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases - -```bash -cd lambdas-download -terraform init -terraform apply -cd .. -``` - -Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you need to specify the build location for all of the zip files. - -```hcl - webhook_lambda_zip = "../../lambda_output/webhook.zip" - runner_binaries_syncer_lambda_zip = "../../lambda_output/runner-binaries-syncer.zip" - runners_lambda_zip = "../../lambda_output/runners.zip" -``` - -### GitHub App Configuration - -Before running Terraform, ensure the GitHub app is configured. See the [configuration details](../../README.md#usages) for more details. +@@ Usages ### Packer Image @@ -52,17 +15,17 @@ You will need to build your image. This example deployment uses the image exampl To use your image in the terraform modules you will need to set some values on the module. -Assuming you have built the `linux-amzn2` image which has a pre-defined AMI name in the following format `github-runner-amzn2-x86_64-YYYYMMDDhhmm` you can use the following values. +Assuming you have built the `linux-al2023` image which has a pre-defined AMI name in the following format `github-runner-al2023-x86_64-YYYYMMDDhhmm` you can use the following values. ```hcl module "runners" { ... # set the name of the ami to use - ami_filter = { name = ["github-runner-amzn2-x86_64-2021*"] } + ami_filter = { name = ["github-runner-al2023-x86_64-2023*"], state = ["available"] } # provide the owner id of ami_owners = [""] - enabled_userdata = false + enable_userdata = false ... } ``` @@ -86,10 +49,56 @@ terraform init terraform apply ``` -You can receive the webhook details by running: +The module will try to update the GitHub App webhook and secret (only linux/mac). You can receive the webhook details by running: ```bash -terraform output -raw webhook_secret +terraform output webhook_secret ``` -Be-aware some shells will print some end of line character `%`. + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | 5.31.0 | +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ami\_name\_filter](#input\_ami\_name\_filter) | AMI name filter for the action runner AMI. By default amazon linux 2 is used. | `string` | `"github-runner-al2023-x86_64-*"` | no | +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux,windows). | `string` | `"linux"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/prebuilt/lambdas-download/main.tf b/examples/prebuilt/lambdas-download/main.tf deleted file mode 100644 index 87f31bd8a9..0000000000 --- a/examples/prebuilt/lambdas-download/main.tf +++ /dev/null @@ -1,25 +0,0 @@ -locals { - version = "" -} - -module "lambdas" { - source = "../../../modules/download-lambda" - lambdas = [ - { - name = "webhook" - tag = local.version - }, - { - name = "runners" - tag = local.version - }, - { - name = "runner-binaries-syncer" - tag = local.version - } - ] -} - -output "files" { - value = module.lambdas.files -} diff --git a/examples/prebuilt/main.tf b/examples/prebuilt/main.tf index 80d6781356..5e5f23703c 100644 --- a/examples/prebuilt/main.tf +++ b/examples/prebuilt/main.tf @@ -27,23 +27,23 @@ module "runners" { enable_organization_runners = false github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } - webhook_lambda_zip = "lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "lambdas-download/runners.zip" + webhook_lambda_zip = "../lambdas-download/webhook.zip" + runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + runners_lambda_zip = "../lambdas-download/runners.zip" - runner_extra_labels = "default,example" + runner_extra_labels = ["default", "example"] runner_os = var.runner_os # configure your pre-built AMI - enabled_userdata = false - ami_filter = { name = [var.ami_name_filter] } - ami_owners = [data.aws_caller_identity.current.account_id] + enable_userdata = false + ami_filter = { name = [var.ami_name_filter], state = ["available"] } + ami_owners = [data.aws_caller_identity.current.account_id] # Look up runner AMI ID from an AWS SSM parameter (overrides ami_filter at instance launch time) # NOTE: the parameter must be managed outside of this module (e.g. in a runner AMI build workflow) @@ -61,3 +61,15 @@ module "runners" { # override scaling down scale_down_schedule_expression = "cron(* * * * ? *)" } + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + depends_on = [module.runners] + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint +} diff --git a/examples/prebuilt/variables.tf b/examples/prebuilt/variables.tf index 5d7fc9aaaa..833ab69a4d 100644 --- a/examples/prebuilt/variables.tf +++ b/examples/prebuilt/variables.tf @@ -1,14 +1,22 @@ +variable "github_app" { + description = "GitHub for API usages." -variable "github_app_key_base64" {} - -variable "github_app_id" {} + type = object({ + id = string + key_base64 = string + }) +} variable "runner_os" { + description = "The EC2 Operating System type to use for action runner instances (linux,windows)." + type = string default = "linux" } variable "ami_name_filter" { + description = "AMI name filter for the action runner AMI. By default amazon linux 2 is used." + type = string - default = "github-runner-amzn2-x86_64-*" + default = "github-runner-al2023-x86_64-*" } diff --git a/examples/prebuilt/versions.tf b/examples/prebuilt/versions.tf index 376c182312..349e8243a5 100644 --- a/examples/prebuilt/versions.tf +++ b/examples/prebuilt/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/examples/termination-watcher/.terraform.lock.hcl b/examples/termination-watcher/.terraform.lock.hcl new file mode 100644 index 0000000000..d95b76d2be --- /dev/null +++ b/examples/termination-watcher/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.40.0" + constraints = "~> 5.27" + hashes = [ + "h1:KEqMoJwLw6Z9bTO4K8nPVvQQa6YiM+bvz89Sw7tNFJw=", + "zh:11f177a2385703740bd26d0652d3dba08575101d7639f386ce5637bdb0e29a13", + "zh:203fc43e69634f1bd487a9dc24b01944dfd568beac78e491f26677d103d343ed", + "zh:3697ebad4929da30ea98276a85d4ce5ebfc48508f4dd149e17e1dcdc7f306c6e", + "zh:421e0799756587e728f75a9024b8d4e38707cd6d65cf0710cb8d189062c85a58", + "zh:4be2adcd4c32a66159c532908f0d425d793c814b3686832e9af549b1515ae032", + "zh:55778b32470212ce6bbfd402529c88e7ea6ba34b0882f85d6ea001ff5c6255a5", + "zh:689a4c1fd1e1d5dab7b169759389c76f25e366f19a470971674321d6fca09791", + "zh:68a23eda608573a053e8738894457bd0c11766bc243e68826c78ab6b5a144710", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a1580115c22564e5752e569dc40482503de6cced44da3e9431885cd9d4bf18ea", + "zh:b127756d7ee513691e76c211570580c10eaa2f7a7e4fd27c3566a48ec214991c", + "zh:b7ccea7a759940c8dcf8726272eed6653eed0b31f7223f71e829a344627afd39", + "zh:bb130fc50494fd45406e04b44d242da9a8f138a4a43feb65cf9e86d13aa13629", + "zh:cf1c972c90d5f22c9705274a33792275e284a0a3fcac12ce4083b5a4480463f4", + "zh:ebe60d3887b23703ca6a4c65b15c6d7b8d93ba27a028d996d17882fe6e98d5c0", + ] +} diff --git a/examples/termination-watcher/README.md b/examples/termination-watcher/README.md new file mode 100644 index 0000000000..bdbc46bd00 --- /dev/null +++ b/examples/termination-watcher/README.md @@ -0,0 +1,53 @@ +# Termination watcher + +This module shows how to use the termination watcher stand-alone. + +## Usages + +Esnure your have the lambda for the termination locally build. By default the one in the lambdas folder will be used. + +Build lambda's (requires node and yarn). + +```bash +cd lambdas +yarn install && yarn dist +``` + +Next switch to this example directory. + +```bash +terraform init +terraform apply +``` + +Once a Spot instance is terminated a log line and metric will be updated. Spot instance termination can be simulated using the Amazon [Fault Injection Service](https://docs.aws.amazon.com/fis/latest/userguide/what-is.html) (FIS). In thw web console you can simply initiate a spot instance failure by navigate in the EC2 console to Spot Requests and choose the action initiate a spot termination event. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [spot\_termination\_watchter](#module\_spot\_termination\_watchter) | ../../modules/termination-watcher | n/a | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +No outputs. + diff --git a/examples/termination-watcher/main.tf b/examples/termination-watcher/main.tf new file mode 100644 index 0000000000..3580b298ed --- /dev/null +++ b/examples/termination-watcher/main.tf @@ -0,0 +1,13 @@ +module "spot_termination_watchter" { + source = "../../modules/termination-watcher" + + config = { + enable_metric = { + spot_warning = true + } + prefix = "global" + tag_filters = { + "ghr:Application" = "github-action-runner" + } + } +} \ No newline at end of file diff --git a/examples/termination-watcher/versions.tf b/examples/termination-watcher/versions.tf new file mode 100644 index 0000000000..c934712b56 --- /dev/null +++ b/examples/termination-watcher/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1" +} diff --git a/examples/ubuntu/.terraform.lock.hcl b/examples/ubuntu/.terraform.lock.hcl index 7556f27ad3..60a47db0b8 100644 --- a/examples/ubuntu/.terraform.lock.hcl +++ b/examples/ubuntu/.terraform.lock.hcl @@ -2,59 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.15.1" - constraints = ">= 3.63.0, ~> 4.0, ~> 4.15" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:KNkM4pOCRzbjlGoCxt4Yl4qGUESLQ2uKIOSHb+aiMlY=", - "zh:1d944144f8d613b8090c0c8391e4b205ca036086d70aceb4cdf664856fa8410c", - "zh:2a0ca16a6b12c0ac509f64512f80bd2ed6e7ea0ec369212efd4be3fa65e9773d", - "zh:3f9efdce4f1c320ffd061e8715e1d031deac1be0b959eaa60c25a274925653e4", - "zh:4cf82f3267b0c3e08be29b0345f711ab84ea1ea75f0e8ce81f5a2fe635ba67b4", - "zh:58474a0b7da438e1bcd53e87f10e28830836ff9b46cce5f09413c90952ae4f78", - "zh:6eb1be8afb0314b6b8424fe212b13beeb04f3f24692f0f3ee86c5153c7eb2e63", - "zh:8022da7d3b050d452ce6c679844e13729bdb4e1b3e75dcf68931af17a06b9277", - "zh:8e2683d00fff1df43440d6e7c04a2c1eb432c7d5dacff32fe8ce9045bc948fe6", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b0c22d9a306e8ac2de57b5291a3d0a7a2c1713e33b7d076005662451afdc4d29", - "zh:ba6b7d7d91388b636145b133da6b4e32620cdc8046352e2dc8f3f0f81ff5d2e2", - "zh:d38a816eb60f4419d99303136a3bb61a0d2df3ca8a1dce2ced9b99bf23efa9f7", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.3" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:FvRIEgCmAezgZUqb2F+PZ9WnSSnR5zbEM2ZI+GLmbMk=", - "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", - "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", - "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", - "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", - "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", - "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", - "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", - "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", - "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", - "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.2.0" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:NvMyFNHHq65GUNyBGjLuLD4ABA6sTlRebZCIK5OtvFU=", - "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", - "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", - "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", - "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", - "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", - "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", - "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", - "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", - "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", - "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/ubuntu/README.md b/examples/ubuntu/README.md index 211e60d2e7..c8f52e7ab8 100644 --- a/examples/ubuntu/README.md +++ b/examples/ubuntu/README.md @@ -1,19 +1,21 @@ -# Action runners deployment ubuntu example +# Ubuntu example + +> This example will be removed soon. Please check the example for epehemeral runners to see how to setup ubuntu based runner. This module shows how to create GitHub action runners using an Ubuntu AMI. Lambda release will be downloaded from GitHub. ## Usages -Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. +Steps for the full setup, such as creating a GitHub app can be found in the [docs](https://philips-labs.github.io/terraform-aws-github-runner/getting-started/). First download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, there is a simple build script in `/.ci/build.sh`. In the `main.tf` you can simply remove the location of the lambda zip files, the default location will work in this case. > Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see https://github.com/philips-labs/terraform-aws-github-runner/releases ```bash -cd lambdas-download +cd ../lambdas-download terraform init -terraform apply -cd .. +terraform apply -var=module_version= +cd - ``` Before running Terraform, ensure the GitHub app is configured. @@ -22,3 +24,54 @@ Before running Terraform, ensure the GitHub app is configured. terraform init terraform apply ``` + +The module will try to update the GitHub App webhook and secret (only linux/mac). You can receive the webhook details by running: + +```bash +terraform output webhook_secret +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [runners](#output\_runners) | n/a | +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/ubuntu/lambdas-download/main.tf b/examples/ubuntu/lambdas-download/main.tf deleted file mode 100644 index 87f31bd8a9..0000000000 --- a/examples/ubuntu/lambdas-download/main.tf +++ /dev/null @@ -1,25 +0,0 @@ -locals { - version = "" -} - -module "lambdas" { - source = "../../../modules/download-lambda" - lambdas = [ - { - name = "webhook" - tag = local.version - }, - { - name = "runners" - tag = local.version - }, - { - name = "runner-binaries-syncer" - tag = local.version - } - ] -} - -output "files" { - value = module.lambdas.files -} diff --git a/examples/ubuntu/main.tf b/examples/ubuntu/main.tf index 52b9edb6c6..ecdf5f473a 100644 --- a/examples/ubuntu/main.tf +++ b/examples/ubuntu/main.tf @@ -7,9 +7,6 @@ resource "random_id" "random" { byte_length = 20 } -data "aws_caller_identity" "current" {} - - module "base" { source = "../base" @@ -30,8 +27,8 @@ module "runners" { } github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } @@ -40,7 +37,7 @@ module "runners" { # runners_lambda_zip = "lambdas-download/runners.zip" enable_organization_runners = false - runner_extra_labels = "default,example" + runner_extra_labels = ["default", "example"] # enable access to the runners via SSM enable_ssm_on_runners = true @@ -54,16 +51,17 @@ module "runners" { ami_owners = ["099720109477"] # Canonical's Amazon account ID ami_filter = { - name = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] + name = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"], + state = ["available"] } # Custom build AMI, no custom userdata needed. # option 2: Build custom AMI see ../../images/ubuntu-focal # disable lines above (option 1) and enable the ones below - # ami_filter = { name = ["github-runner-ubuntu-focal-amd64-*"] } + # ami_filter = { name = ["github-runner-ubuntu-focal-amd64-*"], state = ["available"] } + # data "aws_caller_identity" "current" {} # ami_owners = [data.aws_caller_identity.current.account_id] - block_device_mappings = [{ # Set the block device name for Ubuntu root device device_name = "/dev/sda1" @@ -101,7 +99,7 @@ module "runners" { # Uncomment to enable ephemeral runners # delay_webhook_event = 0 # enable_ephemeral_runners = true - # enabled_userdata = true + # enable_userdata = true # Uncommet idle config to have idle runners from 9 to 5 in time zone Amsterdam # idle_config = [{ @@ -113,3 +111,15 @@ module "runners" { # Enable logging all commands of user_data, secrets will be logged!!! # enable_user_data_debug_logging_runner = true } + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + depends_on = [module.runners] + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint +} diff --git a/examples/ubuntu/providers.tf b/examples/ubuntu/providers.tf index 37e252415a..5e9cb34d29 100644 --- a/examples/ubuntu/providers.tf +++ b/examples/ubuntu/providers.tf @@ -5,10 +5,10 @@ provider "aws" { Example = local.environment } } - // If you use roles with specific permissions please add your role - // assume_role { - // role_arn = "arn:aws:iam::123456789012:role/MyAdminRole" - // } + # If you use roles with specific permissions please add your role + # assume_role { + # role_arn = "arn:aws:iam::123456789012:role/MyAdminRole" + # } } provider "random" { diff --git a/examples/ubuntu/variables.tf b/examples/ubuntu/variables.tf index 69dcd0c61c..d8b5356484 100644 --- a/examples/ubuntu/variables.tf +++ b/examples/ubuntu/variables.tf @@ -1,4 +1,8 @@ +variable "github_app" { + description = "GitHub for API usages." -variable "github_app_key_base64" {} - -variable "github_app_id" {} + type = object({ + id = string + key_base64 = string + }) +} diff --git a/examples/ubuntu/versions.tf b/examples/ubuntu/versions.tf index 376c182312..349e8243a5 100644 --- a/examples/ubuntu/versions.tf +++ b/examples/ubuntu/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/examples/ubuntu/vpc.tf b/examples/ubuntu/vpc.tf deleted file mode 100644 index 6b19a06b3f..0000000000 --- a/examples/ubuntu/vpc.tf +++ /dev/null @@ -1,21 +0,0 @@ -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "3.11.2" - - name = "vpc-${local.environment}" - cidr = "10.0.0.0/16" - - azs = ["${local.aws_region}a", "${local.aws_region}b", "${local.aws_region}c"] - private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"] - public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"] - - enable_dns_hostnames = true - enable_nat_gateway = true - map_public_ip_on_launch = false - single_nat_gateway = true - - tags = { - Environment = local.environment - } - -} diff --git a/examples/windows/.terraform.lock.hcl b/examples/windows/.terraform.lock.hcl index 7556f27ad3..60a47db0b8 100644 --- a/examples/windows/.terraform.lock.hcl +++ b/examples/windows/.terraform.lock.hcl @@ -2,59 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "4.15.1" - constraints = ">= 3.63.0, ~> 4.0, ~> 4.15" + version = "5.31.0" + constraints = ">= 5.0.0, ~> 5.27" hashes = [ - "h1:KNkM4pOCRzbjlGoCxt4Yl4qGUESLQ2uKIOSHb+aiMlY=", - "zh:1d944144f8d613b8090c0c8391e4b205ca036086d70aceb4cdf664856fa8410c", - "zh:2a0ca16a6b12c0ac509f64512f80bd2ed6e7ea0ec369212efd4be3fa65e9773d", - "zh:3f9efdce4f1c320ffd061e8715e1d031deac1be0b959eaa60c25a274925653e4", - "zh:4cf82f3267b0c3e08be29b0345f711ab84ea1ea75f0e8ce81f5a2fe635ba67b4", - "zh:58474a0b7da438e1bcd53e87f10e28830836ff9b46cce5f09413c90952ae4f78", - "zh:6eb1be8afb0314b6b8424fe212b13beeb04f3f24692f0f3ee86c5153c7eb2e63", - "zh:8022da7d3b050d452ce6c679844e13729bdb4e1b3e75dcf68931af17a06b9277", - "zh:8e2683d00fff1df43440d6e7c04a2c1eb432c7d5dacff32fe8ce9045bc948fe6", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b0c22d9a306e8ac2de57b5291a3d0a7a2c1713e33b7d076005662451afdc4d29", - "zh:ba6b7d7d91388b636145b133da6b4e32620cdc8046352e2dc8f3f0f81ff5d2e2", - "zh:d38a816eb60f4419d99303136a3bb61a0d2df3ca8a1dce2ced9b99bf23efa9f7", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.2.3" + version = "2.4.1" + constraints = "~> 2.0" hashes = [ - "h1:FvRIEgCmAezgZUqb2F+PZ9WnSSnR5zbEM2ZI+GLmbMk=", - "zh:04f0978bb3e052707b8e82e46780c371ac1c66b689b4a23bbc2f58865ab7d5c0", - "zh:6484f1b3e9e3771eb7cc8e8bab8b35f939a55d550b3f4fb2ab141a24269ee6aa", - "zh:78a56d59a013cb0f7eb1c92815d6eb5cf07f8b5f0ae20b96d049e73db915b238", + "h1:gpp25uNkYJYzJVnkyRr7RIBVfwLs9GSq2HNnFpTRBg0=", + "zh:244b445bf34ddbd167731cc6c6b95bbed231dc4493f8cc34bd6850cfe1f78528", + "zh:3c330bdb626123228a0d1b1daa6c741b4d5d484ab1c7ae5d2f48d4c9885cc5e9", + "zh:5ff5f9b791ddd7557e815449173f2db38d338e674d2d91800ac6e6d808de1d1d", + "zh:70206147104f4bf26ae67d730c995772f85bf23e28c2c2e7612c74f4dae3c46f", + "zh:75029676993accd6bef933c196b2fad51a9ec8a69a847dbbe96ec8ebf7926cdc", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8aa9950f4c4db37239bcb62e19910c49e47043f6c8587e5b0396619923657797", - "zh:996beea85f9084a725ff0e6473a4594deb5266727c5f56e9c1c7c62ded6addbb", - "zh:9a7ef7a21f48fabfd145b2e2a4240ca57517ad155017e86a30860d7c0c109de3", - "zh:a63e70ac052aa25120113bcddd50c1f3cfe61f681a93a50cea5595a4b2cc3e1c", - "zh:a6e8d46f94108e049ad85dbed60354236dc0b9b5ec8eabe01c4580280a43d3b8", - "zh:bb112ce7efbfcfa0e65ed97fa245ef348e0fd5bfa5a7e4ab2091a9bd469f0a9e", - "zh:d7bec0da5c094c6955efed100f3fe22fca8866859f87c025be1760feb174d6d9", - "zh:fb9f271b72094d07cef8154cd3d50e9aa818a0ea39130bc193132ad7b23076fd", + "zh:7d48d5999fe1fcdae9295a7c3448ac1541f5a24c474bd82df6d4fa3732483f2b", + "zh:b766b38b027f0f84028244d1c2f990431a37d4fc3ac645962924554016507e77", + "zh:bfc7ad301dada204cf51c59d8bd6a9a87de5fddb42190b4d6ba157d6e08a1f10", + "zh:c902b527702a8c5e2c25a6637d07bbb1690cb6c1e63917a5f6dc460efd18d43f", + "zh:d68ae0e1070cf429c46586bc87580c3ed113f76241da2b6e4f1a8348126b3c46", + "zh:f4903fd89f7c92a346ae9e666c2d0b6884c4474ae109e9b4bd15e7efaa4bfc29", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.2" + constraints = "~> 3.0" + hashes = [ + "h1:IMVAUHKoydFrlPrl9OzasDnw/8ntZFerCC9iXw1rXQY=", + "zh:3248aae6a2198f3ec8394218d05bd5e42be59f43a3a7c0b71c66ec0df08b69e7", + "zh:32b1aaa1c3013d33c245493f4a65465eab9436b454d250102729321a44c8ab9a", + "zh:38eff7e470acb48f66380a73a5c7cdd76cc9b9c9ba9a7249c7991488abe22fe3", + "zh:4c2f1faee67af104f5f9e711c4574ff4d298afaa8a420680b0cb55d7bbc65606", + "zh:544b33b757c0b954dbb87db83a5ad921edd61f02f1dc86c6186a5ea86465b546", + "zh:696cf785090e1e8cf1587499516b0494f47413b43cb99877ad97f5d0de3dc539", + "zh:6e301f34757b5d265ae44467d95306d61bef5e41930be1365f5a8dcf80f59452", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:913a929070c819e59e94bb37a2a253c228f83921136ff4a7aa1a178c7cce5422", + "zh:aa9015926cd152425dbf86d1abdbc74bfe0e1ba3d26b3db35051d7b9ca9f72ae", + "zh:bb04798b016e1e1d49bcc76d62c53b56c88c63d6f2dfe38821afef17c416a0e1", + "zh:c23084e1b23577de22603cff752e59128d83cfecc2e6819edadd8cf7a10af11e", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.2.0" + version = "3.6.0" + constraints = "~> 3.0" hashes = [ - "h1:NvMyFNHHq65GUNyBGjLuLD4ABA6sTlRebZCIK5OtvFU=", - "zh:2960977ce9a7d6a7d3e934e75ec5814735626f95c186ad95a9102344a1a38ac1", - "zh:2fd012abfabe7076f3f2f402eeef4970e20574d20ffec57c162b02b6e848c32f", - "zh:4cd3234671cf01c913023418b227eb78b0659f2cd2e0b387be1f0bb607d29889", - "zh:52e695b4fa3fae735ffc901edff8183745f980923510a744db7616e8f10dc499", + "h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=", + "zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d", + "zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211", + "zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829", + "zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d", + "zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:848b4a294e5ba15192ee4bfd199c07f60a437d7572efcd2d89db036e1ebc0e6e", - "zh:9d49aa432a05748a9527e95448cebee1238c87c97c7e8dec694bfd709683f9c7", - "zh:b4ad4cf289d3f7408649b74b8639918833613f2a1f3cf51b51f4b2fdaa412dd2", - "zh:c1544c4b416096fb8d8dbf84c4488584a2844a30dd533b957e9e9e60a165f24e", - "zh:dc737d6b4591cad8c9a1d0b347e587e846d8d901789b29b4dd401b6cdf82c017", - "zh:f5645fd39f749dbbf847cbdc87ba0dbd141143f12917a6a8904faf8a9b64111e", - "zh:fdedf610e0d020878a8f1fedda8105e0c33a7e23c4792fca54460685552de308", + "zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17", + "zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21", + "zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839", + "zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0", + "zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c", + "zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e", ] } diff --git a/examples/windows/README.md b/examples/windows/README.md index 8f3e572586..855cf697b0 100644 --- a/examples/windows/README.md +++ b/examples/windows/README.md @@ -1,10 +1,13 @@ -# Action runners deployment windows example +# Windows runners + + +> This example will be removed soon. Please check the example for epehemeral runners to see how to setup Windows based runner. This module shows how to create GitHub action runners using an Windows Runners. Lambda release will be downloaded from GitHub. ## Usages -Steps for the full setup, such as creating a GitHub app can be found in the root module's [README](../../README.md). First, download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, for which there is a build script available at `/.ci/build.sh`. In the `main.tf` you can remove the location of the lambda zip files, the default location will work in this case. +Steps for the full setup, such as creating a GitHub app can be found in the [docs](https://philips-labs.github.io/terraform-aws-github-runner/getting-started/). First, download the Lambda releases from GitHub. Alternatively you can build the lambdas locally with Node or Docker, for which there is a build script available at `/.ci/build.sh`. In the `main.tf` you can remove the location of the lambda zip files, the default location will work in this case. > Ensure you have set the version in `lambdas-download/main.tf` for running the example. The version needs to be set to a GitHub release version, see @@ -24,3 +27,54 @@ terraform apply ``` _**Note**_: It can take upwards of ten minutes for a runner to start processing jobs, and about as long for logs to start showing up. It's recommend that scale the runners via a warm-up job and then keep them idled. + +The module will try to update the GitHub App webhook and secret (only linux/mac). You can receive the webhook details by running: + +```bash +terraform output webhook_secret +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [local](#requirement\_local) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | 3.6.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [base](#module\_base) | ../base | n/a | +| [runners](#module\_runners) | ../../ | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | ../../modules/webhook-github-app | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_id.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [runners](#output\_runners) | n/a | +| [webhook\_endpoint](#output\_webhook\_endpoint) | n/a | +| [webhook\_secret](#output\_webhook\_secret) | n/a | + diff --git a/examples/windows/lambdas-download/README.md b/examples/windows/lambdas-download/README.md new file mode 100644 index 0000000000..a9a0b890e9 --- /dev/null +++ b/examples/windows/lambdas-download/README.md @@ -0,0 +1,31 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [lambdas](#module\_lambdas) | ../../../modules/download-lambda | n/a | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [files](#output\_files) | n/a | + \ No newline at end of file diff --git a/examples/windows/lambdas-download/versions.tf b/examples/windows/lambdas-download/versions.tf new file mode 100644 index 0000000000..c934712b56 --- /dev/null +++ b/examples/windows/lambdas-download/versions.tf @@ -0,0 +1,3 @@ +terraform { + required_version = ">= 1" +} diff --git a/examples/windows/main.tf b/examples/windows/main.tf index a4233be5ef..fea31e79e9 100644 --- a/examples/windows/main.tf +++ b/examples/windows/main.tf @@ -23,8 +23,8 @@ module "runners" { prefix = local.environment github_app = { - key_base64 = var.github_app_key_base64 - id = var.github_app_id + key_base64 = var.github_app.key_base64 + id = var.github_app.id webhook_secret = random_id.random.hex } @@ -35,7 +35,7 @@ module "runners" { enable_organization_runners = false # no need to add extra windows tag here as it is automatically added by GitHub - runner_extra_labels = "default,example" + runner_extra_labels = ["default", "example"] # Set the OS to Windows runner_os = "windows" @@ -53,3 +53,15 @@ module "runners" { # override scaling down for testing scale_down_schedule_expression = "cron(* * * * ? *)" } + +module "webhook_github_app" { + source = "../../modules/webhook-github-app" + depends_on = [module.runners] + + github_app = { + key_base64 = var.github_app.key_base64 + id = var.github_app.id + webhook_secret = random_id.random.hex + } + webhook_endpoint = module.runners.webhook.endpoint +} diff --git a/examples/windows/variables.tf b/examples/windows/variables.tf index 69dcd0c61c..d8b5356484 100644 --- a/examples/windows/variables.tf +++ b/examples/windows/variables.tf @@ -1,4 +1,8 @@ +variable "github_app" { + description = "GitHub for API usages." -variable "github_app_key_base64" {} - -variable "github_app_id" {} + type = object({ + id = string + key_base64 = string + }) +} diff --git a/examples/windows/versions.tf b/examples/windows/versions.tf index 376c182312..349e8243a5 100644 --- a/examples/windows/versions.tf +++ b/examples/windows/versions.tf @@ -2,14 +2,16 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } local = { - source = "hashicorp/local" + source = "hashicorp/local" + version = "~> 2.0" } random = { - source = "hashicorp/random" + source = "hashicorp/random" + version = "~> 3.0" } } - required_version = ">= 1" + required_version = ">= 1.3.0" } diff --git a/images/README.md b/images/README.md index a3cbe7bec9..d3599710ae 100644 --- a/images/README.md +++ b/images/README.md @@ -1,17 +1,21 @@ # Prebuilt Images +> :warning: These images are provided as an example/ + The images inside this folder are pre-built images designed to shorten the boot time of your runners and make using ephemeral runners a faster experience. -These images share the same scripting as used in the user-data mechanism in `/modules/runners/templates/`. We use a `tempaltefile` mechanism to insert the relevant script fragments into the scripts used for provisioning the images. +These images share the same scripting as used in the user-data mechanism in `/modules/runners/templates/`. We use a `templatefile` mechanism to insert the relevant script fragments into the scripts used for provisioning the images. + +The examples in `linux-al2023` and `windows-core-2019` also upload a `start-runner` script that uses the exact same startup process as used in the user-data mechanism. This means that the image created here does not need any extra scripts injected or changes to boot up and connect to GH. -The examples in `linux-amzn2` and `windows-core-2019` also upload a `start-runner` script that uses the exact same startup process as used in the user-data mechanism. This means that the image created here does not need any extra scripts injected or changes to boot up and connect to GH. +To remove old images the [AMI house keeper module](https://philips-labs.github.io/terraform-aws-github-runner/modules/public/ami-housekeeper/) can be used. ## Building your own To build these images you first need to install packer. You will also need an amazon account and to have provisioned your credentials for packer to consume. -Assuming you are building the `linux-amzn2` image. Then run the following from within the `linux-amzn2` folder +Assuming you are building the `linux-al2023` image. Then run the following from within the `linux-al2023` folder ```bash packer init . @@ -25,13 +29,13 @@ Your image will then begin to build inside AWS and when finished you will be pro To use your image in the terraform modules you will need to set some values on the module. -Assuming you have built the `linux-amzn2` image which has a pre-defined AMI name in the following format `github-runner-amzn2-x86_64-YYYYMMDDhhmm` you can use the following values. +Assuming you have built the `linux-al2023` image which has a pre-defined AMI name in the following format `github-runner-al2023-x86_64-YYYYMMDDhhmm` you can use the following values. ```hcl # set the name of the ami to use -ami_filter = { name = ["github-runner-amzn2-x86_64-2021*"] } -# provide the owner id of +ami_filter = { name = ["github-runner-al2023-x86_64-2023*"] } +# provide the owner id of ami_owners = [""] -enabled_userdata = false +enable_userdata = false ``` diff --git a/images/linux-amzn2/github_agent.linux.pkr.hcl b/images/linux-al2023/github_agent.linux.pkr.hcl similarity index 68% rename from images/linux-amzn2/github_agent.linux.pkr.hcl rename to images/linux-al2023/github_agent.linux.pkr.hcl index 54ef6664f6..ac8c4dff40 100644 --- a/images/linux-amzn2/github_agent.linux.pkr.hcl +++ b/images/linux-al2023/github_agent.linux.pkr.hcl @@ -8,9 +8,8 @@ packer { } variable "runner_version" { - description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases" - type = string - default = "2.295.0" + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null } variable "region" { @@ -78,16 +77,36 @@ variable "custom_shell_commands" { default = [] } +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-amzn2-x86_64-${formatdate("YYYYMMDDhhmm", timestamp())}" - instance_type = var.instance_type - region = var.region - security_group_id = var.security_group_id - subnet_id = var.subnet_id - associate_public_ip_address = var.associate_public_ip_address + ami_name = "github-runner-al2023-x86_64-${formatdate("YYYYMMDDhhmm", timestamp())}" + instance_type = var.instance_type + region = var.region + security_group_id = var.security_group_id + subnet_id = var.subnet_id + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip + source_ami_filter { filters = { - name = "amzn2-ami-kernel-5.*-hvm-*-x86_64-gp2" + name = "al2023-ami-2023.*-kernel-6.*-x86_64" root-device-type = "ebs" virtualization-type = "hvm" } @@ -99,7 +118,7 @@ source "amazon-ebs" "githubrunner" { var.global_tags, var.ami_tags, { - OS_Version = "amzn2" + OS_Version = "al2023" Release = "Latest" Base_AMI_Name = "{{ .SourceAMIName }}" }) @@ -125,9 +144,9 @@ build { provisioner "shell" { environment_vars = [] inline = concat([ - "sudo yum update -y", - "sudo yum install -y amazon-cloudwatch-agent curl jq git", - "sudo amazon-linux-extras install docker", + "sudo dnf upgrade-minimal -y", + "sudo dnf install -y amazon-cloudwatch-agent jq git docker", + "sudo dnf install -y --allowerasing curl", "sudo systemctl enable docker.service", "sudo systemctl enable containerd.service", "sudo service docker start", @@ -148,7 +167,7 @@ build { provisioner "shell" { environment_vars = [ - "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${var.runner_version}/actions-runner-linux-x64-${var.runner_version}.tar.gz" + "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-x64-${local.runner_version}.tar.gz" ] inline = [ "sudo chmod +x /tmp/install-runner.sh", @@ -159,7 +178,7 @@ build { provisioner "file" { content = templatefile("../start-runner.sh", { - start_runner = templatefile("../../modules/runners/templates/start-runner.sh", {}) + start_runner = templatefile("../../modules/runners/templates/start-runner.sh", { metadata_tags = "enabled" }) }) destination = "/tmp/start-runner.sh" } @@ -171,4 +190,8 @@ build { ] } + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } } diff --git a/images/ubuntu-focal/github_agent.ubuntu.pkr.hcl b/images/ubuntu-focal/github_agent.ubuntu.pkr.hcl index 753bc06d15..56cb65ee5b 100644 --- a/images/ubuntu-focal/github_agent.ubuntu.pkr.hcl +++ b/images/ubuntu-focal/github_agent.ubuntu.pkr.hcl @@ -8,9 +8,8 @@ packer { } variable "runner_version" { - description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases" - type = string - default = "2.286.1" + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null } variable "region" { @@ -78,13 +77,32 @@ variable "custom_shell_commands" { default = [] } +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-ubuntu-focal-amd64-${formatdate("YYYYMMDDhhmm", timestamp())}" - instance_type = var.instance_type - region = var.region - security_group_id = var.security_group_id - subnet_id = var.subnet_id - associate_public_ip_address = var.associate_public_ip_address + ami_name = "github-runner-ubuntu-focal-amd64-${formatdate("YYYYMMDDhhmm", timestamp())}" + instance_type = var.instance_type + region = var.region + security_group_id = var.security_group_id + subnet_id = var.subnet_id + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip source_ami_filter { filters = { @@ -127,6 +145,7 @@ build { "DEBIAN_FRONTEND=noninteractive" ] inline = concat([ + "sudo cloud-init status --wait", "sudo apt-get -y update", "sudo apt-get -y install ca-certificates curl gnupg lsb-release", "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg", @@ -158,7 +177,7 @@ build { provisioner "shell" { environment_vars = [ - "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${var.runner_version}/actions-runner-linux-x64-${var.runner_version}.tar.gz" + "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-x64-${local.runner_version}.tar.gz" ] inline = [ "sudo chmod +x /tmp/install-runner.sh", @@ -170,7 +189,7 @@ build { provisioner "file" { content = templatefile("../start-runner.sh", { - start_runner = templatefile("../../modules/runners/templates/start-runner.sh", {}) + start_runner = templatefile("../../modules/runners/templates/start-runner.sh", { metadata_tags = "enabled" }) }) destination = "/tmp/start-runner.sh" } @@ -181,5 +200,8 @@ build { "sudo chmod +x /var/lib/cloud/scripts/per-boot/start-runner.sh", ] } - + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } } diff --git a/images/ubuntu-jammy-arm64/github_agent.ubuntu.pkr.hcl b/images/ubuntu-jammy-arm64/github_agent.ubuntu.pkr.hcl new file mode 100644 index 0000000000..91e2d7f38e --- /dev/null +++ b/images/ubuntu-jammy-arm64/github_agent.ubuntu.pkr.hcl @@ -0,0 +1,207 @@ +packer { + required_plugins { + amazon = { + version = ">= 0.0.2" + source = "github.com/hashicorp/amazon" + } + } +} + +variable "runner_version" { + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null +} + +variable "region" { + description = "The region to build the image in" + type = string + default = "eu-west-1" +} + +variable "security_group_id" { + description = "The ID of the security group Packer will associate with the builder to enable access" + type = string + default = null +} + +variable "subnet_id" { + description = "If using VPC, the ID of the subnet, such as subnet-12345def, where Packer will launch the EC2 instance. This field is required if you are using an non-default VPC" + type = string + default = null +} + +variable "associate_public_ip_address" { + description = "If using a non-default VPC, there is no public IP address assigned to the EC2 instance. If you specified a public subnet, you probably want to set this to true. Otherwise the EC2 instance won't have access to the internet" + type = string + default = null +} + +variable "instance_type" { + description = "The instance type Packer will use for the builder" + type = string + default = "t4g.small" +} + +variable "root_volume_size_gb" { + type = number + default = 8 +} + +variable "ebs_delete_on_termination" { + description = "Indicates whether the EBS volume is deleted on instance termination." + type = bool + default = true +} + +variable "global_tags" { + description = "Tags to apply to everything" + type = map(string) + default = {} +} + +variable "ami_tags" { + description = "Tags to apply to the AMI" + type = map(string) + default = {} +} + +variable "snapshot_tags" { + description = "Tags to apply to the snapshot" + type = map(string) + default = {} +} + +variable "custom_shell_commands" { + description = "Additional commands to run on the EC2 instance, to customize the instance, like installing packages" + type = list(string) + default = [] +} + +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + +source "amazon-ebs" "githubrunner" { + ami_name = "github-runner-ubuntu-jammy-arm64-${formatdate("YYYYMMDDhhmm", timestamp())}" + instance_type = var.instance_type + region = var.region + security_group_id = var.security_group_id + subnet_id = var.subnet_id + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip + + source_ami_filter { + filters = { + name = "*ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-arm64-server-*" + root-device-type = "ebs" + virtualization-type = "hvm" + } + most_recent = true + owners = ["099720109477"] + } + ssh_username = "ubuntu" + tags = merge( + var.global_tags, + var.ami_tags, + { + OS_Version = "ubuntu-jammy" + Release = "Latest" + Base_AMI_Name = "{{ .SourceAMIName }}" + }) + snapshot_tags = merge( + var.global_tags, + var.snapshot_tags, + ) + + launch_block_device_mappings { + device_name = "/dev/sda1" + volume_size = "${var.root_volume_size_gb}" + volume_type = "gp3" + delete_on_termination = "${var.ebs_delete_on_termination}" + } +} + +build { + name = "githubactions-runner" + sources = [ + "source.amazon-ebs.githubrunner" + ] + provisioner "shell" { + environment_vars = [ + "DEBIAN_FRONTEND=noninteractive" + ] + inline = concat([ + "sudo cloud-init status --wait", + "sudo apt-get update", + "sudo apt-get -y install ca-certificates curl gnupg lsb-release", + "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg", + "echo deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null", + "sudo apt-get -y update", + "sudo apt-get -y install docker-ce docker-ce-cli containerd.io jq git unzip build-essential", + "sudo systemctl enable containerd.service", + "sudo service docker start", + "sudo usermod -a -G docker ubuntu", + "sudo curl -f https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/arm64/latest/amazon-cloudwatch-agent.deb -o amazon-cloudwatch-agent.deb", + "sudo dpkg -i amazon-cloudwatch-agent.deb", + "sudo systemctl restart amazon-cloudwatch-agent", + "sudo curl -f https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip -o awscliv2.zip", + "unzip awscliv2.zip", + "sudo ./aws/install", + ], var.custom_shell_commands) + } + + provisioner "file" { + content = templatefile("../install-runner.sh", { + install_runner = templatefile("../../modules/runners/templates/install-runner.sh", { + ARM_PATCH = "" + S3_LOCATION_RUNNER_DISTRIBUTION = "" + RUNNER_ARCHITECTURE = "arm64" + }) + }) + destination = "/tmp/install-runner.sh" + } + + provisioner "shell" { + environment_vars = [ + "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-arm64-${local.runner_version}.tar.gz" + ] + inline = [ + "sudo chmod +x /tmp/install-runner.sh", + "echo ubuntu | tee -a /tmp/install-user.txt", + "sudo RUNNER_ARCHITECTURE=arm64 RUNNER_TARBALL_URL=$RUNNER_TARBALL_URL /tmp/install-runner.sh", + "echo ImageOS=ubuntu22 | tee -a /opt/actions-runner/.env" + ] + } + + provisioner "file" { + content = templatefile("../start-runner.sh", { + start_runner = templatefile("../../modules/runners/templates/start-runner.sh", { metadata_tags = "enabled" }) + }) + destination = "/tmp/start-runner.sh" + } + + provisioner "shell" { + inline = [ + "sudo mv /tmp/start-runner.sh /var/lib/cloud/scripts/per-boot/start-runner.sh", + "sudo chmod +x /var/lib/cloud/scripts/per-boot/start-runner.sh", + ] + } + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } +} diff --git a/images/ubuntu-jammy/github_agent.ubuntu.pkr.hcl b/images/ubuntu-jammy/github_agent.ubuntu.pkr.hcl index 25d068deb4..311bbc5b22 100644 --- a/images/ubuntu-jammy/github_agent.ubuntu.pkr.hcl +++ b/images/ubuntu-jammy/github_agent.ubuntu.pkr.hcl @@ -8,9 +8,8 @@ packer { } variable "runner_version" { - description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases" - type = string - default = "2.294.0" + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null } variable "region" { @@ -78,17 +77,36 @@ variable "custom_shell_commands" { default = [] } +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-ubuntu-jammy-amd64-${formatdate("YYYYMMDDhhmm", timestamp())}" - instance_type = var.instance_type - region = var.region - security_group_id = var.security_group_id - subnet_id = var.subnet_id - associate_public_ip_address = var.associate_public_ip_address + ami_name = "github-runner-ubuntu-jammy-amd64-${formatdate("YYYYMMDDhhmm", timestamp())}" + instance_type = var.instance_type + region = var.region + security_group_id = var.security_group_id + subnet_id = var.subnet_id + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip source_ami_filter { filters = { - name = "*/ubuntu-jammy-22.04-amd64-server-*" + name = "*ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" root-device-type = "ebs" virtualization-type = "hvm" } @@ -127,6 +145,7 @@ build { "DEBIAN_FRONTEND=noninteractive" ] inline = concat([ + "sudo cloud-init status --wait", "sudo apt-get -y update", "sudo apt-get -y install ca-certificates curl gnupg lsb-release", "sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg", @@ -158,7 +177,7 @@ build { provisioner "shell" { environment_vars = [ - "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${var.runner_version}/actions-runner-linux-x64-${var.runner_version}.tar.gz" + "RUNNER_TARBALL_URL=https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-linux-x64-${local.runner_version}.tar.gz" ] inline = [ "sudo chmod +x /tmp/install-runner.sh", @@ -170,7 +189,7 @@ build { provisioner "file" { content = templatefile("../start-runner.sh", { - start_runner = templatefile("../../modules/runners/templates/start-runner.sh", {}) + start_runner = templatefile("../../modules/runners/templates/start-runner.sh", { metadata_tags = "enabled" }) }) destination = "/tmp/start-runner.sh" } @@ -181,5 +200,8 @@ build { "sudo chmod +x /var/lib/cloud/scripts/per-boot/start-runner.sh", ] } - + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } } diff --git a/images/windows-core-2019/github_agent.windows.pkr.hcl b/images/windows-core-2019/github_agent.windows.pkr.hcl index ea8dc20519..5a31604c01 100644 --- a/images/windows-core-2019/github_agent.windows.pkr.hcl +++ b/images/windows-core-2019/github_agent.windows.pkr.hcl @@ -7,10 +7,9 @@ packer { } } -variable "action_runner_url" { - description = "The URL to the tarball of the action runner" - type = string - default = "https://github.com/actions/runner/releases/download/v2.285.1/actions-runner-win-x64-2.285.1.zip" +variable "runner_version" { + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null } variable "region" { @@ -43,12 +42,31 @@ variable "custom_shell_commands" { default = [] } +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-windows-core-2019-${formatdate("YYYYMMDDhhmm", timestamp())}" - communicator = "winrm" - instance_type = var.instance_type - region = var.region - associate_public_ip_address = var.associate_public_ip_address + ami_name = "github-runner-windows-core-2019-${formatdate("YYYYMMDDhhmm", timestamp())}" + communicator = "winrm" + instance_type = var.instance_type + region = var.region + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip source_ami_filter { filters = { @@ -92,8 +110,12 @@ build { provisioner "powershell" { inline = concat([ templatefile("./windows-provisioner.ps1", { - action_runner_url = var.action_runner_url + action_runner_url = "https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-win-x64-${local.runner_version}.zip" }) ], var.custom_shell_commands) } + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } } diff --git a/images/windows-core-2022/github_agent.windows.pkr.hcl b/images/windows-core-2022/github_agent.windows.pkr.hcl index 47ca41b74d..18a5ee93c3 100644 --- a/images/windows-core-2022/github_agent.windows.pkr.hcl +++ b/images/windows-core-2022/github_agent.windows.pkr.hcl @@ -8,9 +8,8 @@ packer { } variable "runner_version" { - description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases" - type = string - default = "2.286.1" + description = "The version (no v prefix) of the runner software to install https://github.com/actions/runner/releases. The latest release will be fetched from GitHub if not provided." + default = null } variable "region" { @@ -54,18 +53,37 @@ variable "custom_shell_commands" { default = [] } +variable "temporary_security_group_source_public_ip" { + description = "When enabled, use public IP of the host (obtained from https://checkip.amazonaws.com) as CIDR block to be authorized access to the instance, when packer is creating a temporary security group. Note: If you specify `security_group_id` then this input is ignored." + type = bool + default = false +} + +data "http" github_runner_release_json { + url = "https://api.github.com/repos/actions/runner/releases/latest" + request_headers = { + Accept = "application/vnd.github+json" + X-GitHub-Api-Version : "2022-11-28" + } +} + +locals { + runner_version = coalesce(var.runner_version, trimprefix(jsondecode(data.http.github_runner_release_json.body).tag_name, "v")) +} + source "amazon-ebs" "githubrunner" { - ami_name = "github-runner-windows-core-2022-${formatdate("YYYYMMDDhhmm", timestamp())}" - communicator = "winrm" - instance_type = "m4.xlarge" - region = var.region - security_group_id = var.security_group_id - subnet_id = var.subnet_id - associate_public_ip_address = var.associate_public_ip_address + ami_name = "github-runner-windows-core-2022-${formatdate("YYYYMMDDhhmm", timestamp())}" + communicator = "winrm" + instance_type = "m4.xlarge" + region = var.region + security_group_id = var.security_group_id + subnet_id = var.subnet_id + associate_public_ip_address = var.associate_public_ip_address + temporary_security_group_source_public_ip = var.temporary_security_group_source_public_ip source_ami_filter { filters = { - name = "Windows_Server-2022-English-Core-ContainersLatest-**" + name = "Windows_Server-2022-English-Full-ECS_Optimized-*" root-device-type = "ebs" virtualization-type = "hvm" } @@ -106,8 +124,12 @@ build { provisioner "powershell" { inline = concat([ templatefile("./windows-provisioner.ps1", { - action_runner_url = "https://github.com/actions/runner/releases/download/v${var.runner_version}/actions-runner-win-x64-${var.runner_version}.zip" + action_runner_url = "https://github.com/actions/runner/releases/download/v${local.runner_version}/actions-runner-win-x64-${local.runner_version}.zip" }) ], var.custom_shell_commands) } + post-processor "manifest" { + output = "manifest.json" + strip_path = true + } } diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.eslintrc.yaml b/lambdas/.eslintrc.yaml similarity index 100% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.eslintrc.yaml rename to lambdas/.eslintrc.yaml diff --git a/lambdas/.gitignore b/lambdas/.gitignore new file mode 100644 index 0000000000..b2e8d65c37 --- /dev/null +++ b/lambdas/.gitignore @@ -0,0 +1,11 @@ +node_modules/ +build/ +dist/ +*.log + +# Ignore all yarn.lock files except the one in the root +**/yarn.lock +!/yarn.lock + + +.nx/cache \ No newline at end of file diff --git a/lambdas/.nvmrc b/lambdas/.nvmrc new file mode 100644 index 0000000000..9a2a0e219c --- /dev/null +++ b/lambdas/.nvmrc @@ -0,0 +1 @@ +v20 diff --git a/lambdas/.prettierignore b/lambdas/.prettierignore new file mode 100644 index 0000000000..d155fdbd59 --- /dev/null +++ b/lambdas/.prettierignore @@ -0,0 +1,4 @@ +# Add files here to ignore them from prettier formatting +/dist +/coverage +/.nx/cache \ No newline at end of file diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.prettierrc b/lambdas/.prettierrc similarity index 100% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.prettierrc rename to lambdas/.prettierrc diff --git a/lambdas/.vscode/settings.json b/lambdas/.vscode/settings.json new file mode 100644 index 0000000000..cce0d7bf09 --- /dev/null +++ b/lambdas/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + + "jest.jestCommandLine": "yarn run test --", +} + \ No newline at end of file diff --git a/lambdas/functions/ami-housekeeper/jest.config.ts b/lambdas/functions/ami-housekeeper/jest.config.ts new file mode 100644 index 0000000000..077707f923 --- /dev/null +++ b/lambdas/functions/ami-housekeeper/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 100, + branches: 100, + functions: 100, + lines: 100, + }, + }, +}; + +export default config; diff --git a/lambdas/functions/ami-housekeeper/package.json b/lambdas/functions/ami-housekeeper/package.json new file mode 100644 index 0000000000..295c5aeb2d --- /dev/null +++ b/lambdas/functions/ami-housekeeper/package.json @@ -0,0 +1,60 @@ +{ + "name": "@terraform-aws-github-runner/ami-housekeeper", + "version": "1.0.0", + "main": "lambda.ts", + "license": "MIT", + "scripts": { + "start": "ts-node-dev src/local.ts", + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "watch": "ts-node-dev --respawn --exit-child src/local.ts", + "build": "ncc build src/lambda.ts -o dist", + "dist": "yarn build && cd dist && zip ../ami-housekeeper.zip index.js", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/jest": "^29.5.12", + "@types/node": "^20.8.9", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "^0.38.1", + "aws-sdk-client-mock": "^3.0.0", + "aws-sdk-client-mock-jest": "^3.0.0", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "jest-mock-extended": "^3.0.6", + "nock": "^13.4.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", + "ts-node-dev": "^2.0.0" + }, + "dependencies": { + "@aws-sdk/client-ec2": "^3.604.0", + "@aws-sdk/client-ssm": "^3.603.0", + "@aws-sdk/types": "^3.433.0", + "@terraform-aws-github-runner/aws-powertools-util": "*", + "@terraform-aws-github-runner/aws-ssm-util": "*", + "cron-parser": "^4.8.1", + "typescript": "^5.4.5" + }, + "nx": { + "includedScripts": [ + "build", + "dist", + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/lambdas/functions/ami-housekeeper/src/ami.test.ts b/lambdas/functions/ami-housekeeper/src/ami.test.ts new file mode 100644 index 0000000000..e5ee85de43 --- /dev/null +++ b/lambdas/functions/ami-housekeeper/src/ami.test.ts @@ -0,0 +1,369 @@ +import { + DeleteSnapshotCommand, + DeregisterImageCommand, + DescribeImagesCommand, + DescribeLaunchTemplateVersionsCommand, + DescribeLaunchTemplatesCommand, + EC2Client, + Image, +} from '@aws-sdk/client-ec2'; +import { + DescribeParametersCommand, + DescribeParametersCommandOutput, + GetParameterCommand, + SSMClient, +} from '@aws-sdk/client-ssm'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; + +import { AmiCleanupOptions, amiCleanup, defaultAmiCleanupOptions } from './ami'; + +process.env.AWS_REGION = 'eu-east-1'; +const deleteAmisOlderThenDays = 30; +const date31DaysAgo = new Date(new Date().setDate(new Date().getDate() - (deleteAmisOlderThenDays + 1))); + +const mockEC2Client = mockClient(EC2Client); +const mockSSMClient = mockClient(SSMClient); + +const imagesInUseSsm: Image[] = [ + { + ImageId: 'ami-ssm0001', + CreationDate: date31DaysAgo.toISOString(), + BlockDeviceMappings: [ + { + Ebs: { + SnapshotId: 'snap-ssm0001', + }, + }, + ], + }, + { + ImageId: 'ami-ssm0002', + }, +]; + +const imagesInUseLaunchTemplates: Image[] = [ + { + ImageId: 'ami-lt0001', + CreationDate: date31DaysAgo.toISOString(), + }, +]; + +const imagesInUse: Image[] = [...imagesInUseSsm, ...imagesInUseLaunchTemplates]; + +const ssmParameters: DescribeParametersCommandOutput = { + Parameters: [ + { + Name: 'ami-id/ami-ssm0001', + Type: 'String', + Version: 1, + }, + { + Name: 'ami-id/ami-ssm0002', + Type: 'String', + Version: 1, + }, + ], + $metadata: { + httpStatusCode: 200, + requestId: '1234', + extendedRequestId: '1234', + cfId: undefined, + attempts: 1, + totalRetryDelay: 0, + }, +}; + +describe("delete AMI's", () => { + beforeEach(() => { + jest.resetAllMocks(); + mockEC2Client.reset(); + mockSSMClient.reset(); + + mockSSMClient.on(DescribeParametersCommand).resolves(ssmParameters); + mockSSMClient.on(GetParameterCommand, { Name: 'ami-id/ami-ssm0001' }).resolves({ + Parameter: { + Name: 'ami-id/ami-ssm0001', + Type: 'String', + Value: 'ami-ssm0001', + Version: 1, + }, + }); + mockSSMClient.on(GetParameterCommand, { Name: 'ami-id/ami-ssm0002' }).resolves({ + Parameter: { + Name: 'ami-id/ami-ssm0002', + Type: 'String', + Value: 'ami-ssm0002', + Version: 1, + }, + }); + + mockEC2Client.on(DescribeLaunchTemplatesCommand).resolves({ + LaunchTemplates: [ + { + LaunchTemplateId: 'lt-1234', + LaunchTemplateName: 'lt-1234', + DefaultVersionNumber: 1, + LatestVersionNumber: 2, + }, + ], + }); + + mockEC2Client + .on(DescribeLaunchTemplateVersionsCommand, { + LaunchTemplateId: 'lt-1234', + }) + .resolves({ + LaunchTemplateVersions: [ + { + LaunchTemplateId: 'lt-1234', + LaunchTemplateName: 'lt-1234', + VersionNumber: 2, + LaunchTemplateData: { + ImageId: 'ami-lt0001', + }, + }, + ], + }); + }); + + mockEC2Client.on(DeregisterImageCommand).resolves({}); + mockEC2Client.on(DeleteSnapshotCommand).resolves({}); + + it('should look up images in SSM, nothing to delete.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: [], + }); + + await amiCleanup({ ssmParameterNames: ['*ami-id'] }); + expect(mockEC2Client).not.toHaveReceivedCommand(DeregisterImageCommand); + expect(mockEC2Client).not.toHaveReceivedCommand(DeleteSnapshotCommand); + expect(mockEC2Client).toHaveReceivedCommand(DescribeLaunchTemplatesCommand); + expect(mockEC2Client).toHaveReceivedCommand(DescribeLaunchTemplateVersionsCommand); + expect(mockSSMClient).toHaveReceivedCommand(DescribeParametersCommand); + expect(mockSSMClient).toHaveReceivedCommandTimes(GetParameterCommand, 2); + expect(mockSSMClient).toHaveReceivedCommandWith(GetParameterCommand, { + Name: 'ami-id/ami-ssm0001', + }); + expect(mockSSMClient).toHaveReceivedCommandWith(GetParameterCommand, { + Name: 'ami-id/ami-ssm0002', + }); + }); + + it('should NOT delete instances in use.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: imagesInUse, + }); + + // rely on defaults, instances imagesInSssm will be deleted as well + await amiCleanup({ + ssmParameterNames: ['*ami-id'], + minimumDaysOld: 0, + }); + expect(mockEC2Client).not.toHaveReceivedCommand(DeregisterImageCommand); + expect(mockEC2Client).not.toHaveReceivedCommand(DeleteSnapshotCommand); + }); + + it('Should rely on defaults if no options are passed.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: [ + { + ImageId: 'ami-notOld', + CreationDate: new Date().toISOString(), + }, + { + ImageId: 'ami-old', + CreationDate: date31DaysAgo.toISOString(), + }, + ], + }); + + // force null values since json does not support undefined + await amiCleanup({ + ssmParameterNames: null, + minimumDaysOld: null, + filters: null, + launchTemplateNames: null, + maxItems: null, + } as unknown as AmiCleanupOptions); + + expect(mockSSMClient).not.toHaveReceivedCommand(DescribeParametersCommand); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeLaunchTemplatesCommand, { + LaunchTemplateNames: undefined, + }); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeImagesCommand, { + Filters: defaultAmiCleanupOptions.amiFilters, + MaxResults: defaultAmiCleanupOptions.maxItems, + Owners: ['self'], + }); + expect(mockEC2Client).toHaveReceivedCommandWith(DeregisterImageCommand, { + ImageId: 'ami-old', + }); + }); + + it('should NOT delete instances in use, SSM not used.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: imagesInUse, + }); + + // rely on defaults, instances imagesInSssm will be deleted as well + await amiCleanup({ + minimumDaysOld: 0, + }); + + // one images in imagesInUseSsm is not deleted since it has no creation date. + expect(mockEC2Client).toHaveReceivedCommandTimes(DeregisterImageCommand, 1); + expect(mockEC2Client).toHaveReceivedCommandTimes(DeleteSnapshotCommand, 1); + expect(mockEC2Client).toHaveReceivedCommandWith(DeregisterImageCommand, { + ImageId: 'ami-ssm0001', + }); + expect(mockEC2Client).toHaveReceivedCommandWith(DeleteSnapshotCommand, { + SnapshotId: 'snap-ssm0001', + }); + }); + + it('should not call delete when no AMIs at all.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: undefined, + }); + mockSSMClient.on(DescribeParametersCommand).resolves({ + Parameters: undefined, + }); + mockEC2Client.on(DescribeLaunchTemplatesCommand).resolves({ + LaunchTemplates: undefined, + }); + + await amiCleanup({ ssmParameterNames: ['*ami-id'] }); + expect(mockEC2Client).not.toHaveReceivedCommand(DeregisterImageCommand); + expect(mockEC2Client).not.toHaveReceivedCommand(DeleteSnapshotCommand); + }); + + it('should filter delete AMIs not in use older then 30 days.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: [ + ...imagesInUse, + { + ImageId: 'ami-old0001', + CreationDate: date31DaysAgo.toISOString(), + BlockDeviceMappings: [ + { + Ebs: { + SnapshotId: 'snap-old0001', + }, + }, + ], + }, + { + ImageId: 'ami-old0002', + CreationDate: date31DaysAgo.toISOString(), + }, + { + ImageId: 'ami-notOld0001', + CreationDate: new Date(new Date().setDate(new Date().getDate() - 1)).toISOString(), + BlockDeviceMappings: [ + { + Ebs: { + SnapshotId: 'snap-notOld0001', + }, + }, + ], + }, + ], + }); + + await amiCleanup({ + minimumDaysOld: deleteAmisOlderThenDays, + ssmParameterNames: ['*ami-id'], + }); + expect(mockEC2Client).toHaveReceivedCommandTimes(DeregisterImageCommand, 2); + expect(mockEC2Client).toHaveReceivedCommandWith(DeregisterImageCommand, { + ImageId: 'ami-old0001', + }); + expect(mockEC2Client).toHaveReceivedCommandWith(DeleteSnapshotCommand, { + SnapshotId: 'snap-old0001', + }); + expect(mockEC2Client).toHaveReceivedCommandWith(DeregisterImageCommand, { + ImageId: 'ami-old0002', + }); + expect(mockEC2Client).not.toHaveReceivedCommandWith(DeregisterImageCommand, { + ImageId: 'ami-notOld0001', + }); + expect(mockEC2Client).not.toHaveReceivedCommandWith(DeleteSnapshotCommand, { + SnapshotId: 'snap-notOld0001', + }); + + expect(mockEC2Client).toHaveReceivedCommandTimes(DeleteSnapshotCommand, 1); + }); + + it('should delete 1 AMIs AMI.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: [ + { + ImageId: 'ami-old0001', + CreationDate: date31DaysAgo.toISOString(), + }, + ], + }); + + await amiCleanup({ + minimumDaysOld: deleteAmisOlderThenDays, + ssmParameterNames: ['*ami-id'], + maxItems: 1, + }); + expect(mockEC2Client).toHaveReceivedCommandTimes(DeregisterImageCommand, 1); + expect(mockEC2Client).toHaveReceivedCommandWith(DeregisterImageCommand, { + ImageId: 'ami-old0001', + }); + expect(mockEC2Client).not.toHaveReceivedCommand(DeleteSnapshotCommand); + }); + + it('should not delete a snapshot if ami deletion fails.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: [ + ...imagesInUse, + { + ImageId: 'ami-old0001', + CreationDate: date31DaysAgo.toISOString(), + BlockDeviceMappings: [ + { + Ebs: { + SnapshotId: 'snap-old0001', + }, + }, + ], + }, + ], + }); + + mockEC2Client.on(DeregisterImageCommand).rejects({}); + + await amiCleanup({ ssmParameterNames: ['*ami-id'] }).catch(() => fail()); + expect(mockEC2Client).toHaveReceivedCommandTimes(DeregisterImageCommand, 1); + expect(mockEC2Client).not.toHaveReceivedCommand(DeleteSnapshotCommand); + }); + + it('should not fail when deleting a snahshot fails.', async () => { + mockEC2Client.on(DescribeImagesCommand, { Owners: ['self'] }).resolves({ + Images: [ + ...imagesInUse, + { + ImageId: 'ami-old0001', + CreationDate: date31DaysAgo.toISOString(), + BlockDeviceMappings: [ + { + Ebs: { + SnapshotId: 'snap-old0001', + }, + }, + ], + }, + ], + }); + + mockEC2Client.on(DeleteSnapshotCommand).rejects({}); + + await amiCleanup({ ssmParameterNames: ['*ami-id'] }).catch(() => fail()); + expect(mockEC2Client).toHaveReceivedCommandTimes(DeregisterImageCommand, 1); + expect(mockEC2Client).toHaveReceivedCommandTimes(DeleteSnapshotCommand, 1); + }); +}); diff --git a/lambdas/functions/ami-housekeeper/src/ami.ts b/lambdas/functions/ami-housekeeper/src/ami.ts new file mode 100644 index 0000000000..1298ff0f6f --- /dev/null +++ b/lambdas/functions/ami-housekeeper/src/ami.ts @@ -0,0 +1,218 @@ +import { + DeleteSnapshotCommand, + DeregisterImageCommand, + DescribeImagesCommand, + DescribeLaunchTemplateVersionsCommand, + DescribeLaunchTemplatesCommand, + EC2Client, + Filter, + Image, +} from '@aws-sdk/client-ec2'; +import { DescribeParametersCommand, GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getTracedAWSV3Client } from '@terraform-aws-github-runner/aws-powertools-util'; + +const logger = createChildLogger('ami'); + +export interface AmiCleanupOptions { + minimumDaysOld?: number; + maxItems?: number; + amiFilters?: Filter[]; + launchTemplateNames?: string[]; + ssmParameterNames?: string[]; + dryRun?: boolean; +} + +interface AmiCleanupOptionsInternal extends AmiCleanupOptions { + minimumDaysOld: number; + maxItems: number; + amiFilters: Filter[]; + launchTemplateNames: string[]; + ssmParameterNames: string[]; + dryRun: boolean; +} + +export const defaultAmiCleanupOptions: AmiCleanupOptions = { + minimumDaysOld: 30, + maxItems: undefined, + amiFilters: [ + { + Name: 'state', + Values: ['available'], + }, + { + Name: 'image-type', + Values: ['machine'], + }, + ], + launchTemplateNames: undefined, + ssmParameterNames: undefined, + dryRun: false, +}; + +function applyDefaults(options: AmiCleanupOptions): AmiCleanupOptions { + return { + minimumDaysOld: options.minimumDaysOld ?? defaultAmiCleanupOptions.minimumDaysOld, + maxItems: options.maxItems ?? defaultAmiCleanupOptions.maxItems, + amiFilters: options.amiFilters ?? defaultAmiCleanupOptions.amiFilters, + launchTemplateNames: options.launchTemplateNames ?? defaultAmiCleanupOptions.launchTemplateNames, + ssmParameterNames: options.ssmParameterNames ?? defaultAmiCleanupOptions.ssmParameterNames, + dryRun: options.dryRun ?? defaultAmiCleanupOptions.dryRun, + }; +} + +/** + * Cleanup AMIs that are not in use anymore. + * + * @param options the cleanup options + */ +async function amiCleanup(options: AmiCleanupOptions): Promise { + const mergedOptions = applyDefaults(options) as AmiCleanupOptionsInternal; + logger.info(`Cleaning up non used AMIs older then ${mergedOptions.minimumDaysOld} days`); + logger.debug('Using the following options', { options: mergedOptions }); + + const amisNotInUse = await getAmisNotInUse(mergedOptions); + + for (const image of amisNotInUse) { + await new Promise((resolve) => setTimeout(resolve, 100)); + await deleteAmi(image, mergedOptions); + } +} + +async function getAmisNotInUse(options: AmiCleanupOptions) { + const amiIdsInSSM = await getAmisReferedInSSM(options); + const amiIdsInTemplates = await getAmiInLatestTemplates(options); + + const ec2Client = getTracedAWSV3Client(new EC2Client({})); + logger.debug('Getting all AMIs from ec2 with filters', { filters: options.amiFilters }); + const amiEc2 = await ec2Client.send( + new DescribeImagesCommand({ + Owners: ['self'], + MaxResults: options.maxItems ? options.maxItems : undefined, + Filters: options.amiFilters, + }), + ); + logger.debug('Found the following AMIs', { amiEc2 }); + + // sort oldest first + amiEc2.Images?.sort((a, b) => { + if (a.CreationDate && b.CreationDate) { + return new Date(a.CreationDate).getTime() - new Date(b.CreationDate).getTime(); + } else { + return 0; + } + }); + logger.info(`found #${amiEc2.Images?.length} images in ec2`); + + logger.info(`found #${amiIdsInSSM.length} images referenced in SSM`); + logger.info(`found #${amiIdsInTemplates.length} images in latest versions of launch templates`); + const filteredAmiEc2 = + amiEc2.Images?.filter( + (image) => !amiIdsInSSM.includes(image.ImageId) && !amiIdsInTemplates.includes(image.ImageId), + ) ?? []; + + logger.info(`found #${filteredAmiEc2.length} images in ec2 not in use.`); + + return filteredAmiEc2; +} + +async function deleteAmi(amiDetails: Image, options: AmiCleanupOptionsInternal): Promise { + // check if ami is older then 30 days + const creationDate = amiDetails.CreationDate ? new Date(amiDetails.CreationDate) : undefined; + const minimumDaysOldDate = new Date(); + minimumDaysOldDate.setDate(minimumDaysOldDate.getDate() - options.minimumDaysOld); + if (!creationDate) { + logger.warn(`ami ${amiDetails.ImageId} has no creation date`); + return; + } else if (creationDate > minimumDaysOldDate) { + logger.debug( + `ami ${amiDetails.Name || amiDetails.ImageId} created on ${amiDetails.CreationDate} is not deleted, ` + + `not older then ${options.minimumDaysOld} days`, + ); + return; + } + + try { + logger.info(`deleting ami ${amiDetails.Name || amiDetails.ImageId} created at ${amiDetails.CreationDate}`); + const ec2Client = getTracedAWSV3Client(new EC2Client({})); + await ec2Client.send(new DeregisterImageCommand({ ImageId: amiDetails.ImageId, DryRun: options.dryRun })); + await deleteSnapshot(options, amiDetails, ec2Client); + } catch (error) { + logger.warn(`Cannot delete ami ${amiDetails.Name || amiDetails.ImageId}`); + logger.debug(`Cannot delete ami ${amiDetails.Name || amiDetails.ImageId}`, { error }); + } +} + +async function deleteSnapshot(options: AmiCleanupOptions, amiDetails: Image, ec2Client: EC2Client) { + amiDetails.BlockDeviceMappings?.map(async (blockDeviceMapping) => { + const snapshotId = blockDeviceMapping.Ebs?.SnapshotId; + if (snapshotId) { + try { + logger.info(`deleting snapshot ${snapshotId} from ami ${amiDetails.ImageId}`); + await ec2Client.send(new DeleteSnapshotCommand({ SnapshotId: snapshotId, DryRun: options.dryRun })); + } catch (error) { + logger.error(`Cannot delete snapshot ${snapshotId} for ${amiDetails.Name || amiDetails.ImageId}`); + logger.debug(`Cannot delete snapshot ${snapshotId} for ${amiDetails.Name || amiDetails.ImageId}`, { error }); + } + } + }); +} + +async function getAmiInLatestTemplates(options: AmiCleanupOptions): Promise<(string | undefined)[]> { + const ec2Client = getTracedAWSV3Client(new EC2Client({})); + const launnchTemplates = await ec2Client.send( + new DescribeLaunchTemplatesCommand({ + LaunchTemplateNames: options.launchTemplateNames, + }), + ); + + // lookup details of latest version of each launch template + const amiIdsInTemplates = await Promise.all( + launnchTemplates.LaunchTemplates?.map(async (launchTemplate) => { + const launchTemplateVersion = await ec2Client.send( + new DescribeLaunchTemplateVersionsCommand({ + LaunchTemplateId: launchTemplate.LaunchTemplateId, + Versions: ['$Default'], + }), + ); + return launchTemplateVersion.LaunchTemplateVersions?.map( + (templateVersion) => templateVersion.LaunchTemplateData?.ImageId, + ).flat(); + }) ?? [], + ); + + return amiIdsInTemplates.flat(); +} + +async function getAmisReferedInSSM(options: AmiCleanupOptions): Promise<(string | undefined)[]> { + if (!options.ssmParameterNames || options.ssmParameterNames.length === 0) { + return []; + } + + const ssmClient = getTracedAWSV3Client(new SSMClient({})); + const ssmParams = await ssmClient.send( + new DescribeParametersCommand({ + ParameterFilters: [ + { + Key: 'Name', + Values: ['ami-id'], + Option: 'Contains', + }, + ], + }), + ); + logger.debug('Found the following SSM parameters', { ssmParams }); + + return await Promise.all( + (ssmParams.Parameters ?? []).map(async (param) => { + const paramValue = await ssmClient.send( + new GetParameterCommand({ + Name: param.Name, + }), + ); + return paramValue.Parameter?.Value; + }), + ); +} + +export { amiCleanup, getAmisNotInUse }; diff --git a/lambdas/functions/ami-housekeeper/src/lambda.test.ts b/lambdas/functions/ami-housekeeper/src/lambda.test.ts new file mode 100644 index 0000000000..918266ae7c --- /dev/null +++ b/lambdas/functions/ami-housekeeper/src/lambda.test.ts @@ -0,0 +1,68 @@ +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { Context } from 'aws-lambda'; +import { mocked } from 'jest-mock'; + +import { AmiCleanupOptions, amiCleanup } from './ami'; +import { handler } from './lambda'; + +jest.mock('./ami'); +jest.mock('@terraform-aws-github-runner/aws-powertools-util'); + +const amiCleanupOptions: AmiCleanupOptions = { + minimumDaysOld: undefined, + maxItems: undefined, + amiFilters: undefined, + launchTemplateNames: undefined, + ssmParameterNames: undefined, +}; + +process.env.AMI_CLEANUP_OPTIONS = JSON.stringify(amiCleanupOptions); + +const context: Context = { + awsRequestId: '1', + callbackWaitsForEmptyEventLoop: false, + functionName: '', + functionVersion: '', + getRemainingTimeInMillis: () => 0, + invokedFunctionArn: '', + logGroupName: '', + logStreamName: '', + memoryLimitInMB: '', + done: () => { + return; + }, + fail: () => { + return; + }, + succeed: () => { + return; + }, +}; + +// Docs for testing async with jest: https://jestjs.io/docs/tutorial-async +describe('Housekeeper ami', () => { + beforeAll(() => { + jest.resetAllMocks(); + }); + + it('should not throw or log in error.', async () => { + const mock = mocked(amiCleanup); + mock.mockImplementation(() => { + return new Promise((resolve) => { + resolve(); + }); + }); + expect(await handler(undefined, context)).resolves; + }); + + it('should not thow only log in error in case of an exception.', async () => { + const logSpy = jest.spyOn(logger, 'error'); + + const error = new Error('An error.'); + const mock = mocked(amiCleanup); + mock.mockRejectedValue(error); + await expect(handler(undefined, context)).resolves.toBeUndefined(); + + expect(logSpy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/lambdas/functions/ami-housekeeper/src/lambda.ts b/lambdas/functions/ami-housekeeper/src/lambda.ts new file mode 100644 index 0000000000..71aa0ecb29 --- /dev/null +++ b/lambdas/functions/ami-housekeeper/src/lambda.ts @@ -0,0 +1,18 @@ +import { logger, setContext } from '@terraform-aws-github-runner/aws-powertools-util'; +import { Context } from 'aws-lambda'; +import 'source-map-support/register'; + +import { amiCleanup } from './ami'; + +export async function handler(event: unknown, context: Context): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + + try { + const config = JSON.parse(process.env.AMI_CLEANUP_OPTIONS); + logger.debug('Clean-up options', { config }); + await amiCleanup(config); + } catch (e) { + logger.error(`${(e as Error).message}`, { error: e as Error }); + } +} diff --git a/lambdas/functions/ami-housekeeper/src/local.ts b/lambdas/functions/ami-housekeeper/src/local.ts new file mode 100644 index 0000000000..c0391e62da --- /dev/null +++ b/lambdas/functions/ami-housekeeper/src/local.ts @@ -0,0 +1,30 @@ +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; + +import { amiCleanup } from './ami'; + +export function run(): void { + amiCleanup({ + minimumDaysOld: 30, + maxItems: 100, + amiFilters: [ + { + Name: 'state', + Values: ['available'], + }, + { + Name: 'image-type', + Values: ['machine'], + }, + { + Name: 'tag:Packer', + Values: ['true'], + }, + ], + }) + .then() + .catch((e) => { + logger.error(e); + }); +} + +run(); diff --git a/lambdas/functions/ami-housekeeper/src/modules.d.ts b/lambdas/functions/ami-housekeeper/src/modules.d.ts new file mode 100644 index 0000000000..3d655b1e61 --- /dev/null +++ b/lambdas/functions/ami-housekeeper/src/modules.d.ts @@ -0,0 +1,5 @@ +declare namespace NodeJS { + export interface ProcessEnv { + AMI_CLEANUP_OPTIONS: string; + } +} diff --git a/lambdas/functions/ami-housekeeper/tsconfig.json b/lambdas/functions/ami-housekeeper/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/functions/ami-housekeeper/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/lambdas/functions/control-plane/jest.config.ts b/lambdas/functions/control-plane/jest.config.ts new file mode 100644 index 0000000000..db8fdc0160 --- /dev/null +++ b/lambdas/functions/control-plane/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 97.99, + branches: 96.04, + functions: 97.53, + lines: 98.3, + }, + }, +}; + +export default config; diff --git a/lambdas/functions/control-plane/package.json b/lambdas/functions/control-plane/package.json new file mode 100644 index 0000000000..8d4ed16884 --- /dev/null +++ b/lambdas/functions/control-plane/package.json @@ -0,0 +1,65 @@ +{ + "name": "@terraform-aws-github-runner/control-plane", + "version": "1.0.0", + "main": "lambda.ts", + "license": "MIT", + "scripts": { + "start": "ts-node-dev src/local.ts", + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "watch": "ts-node-dev --respawn --exit-child --files src/local.ts", + "build": "ncc build src/lambda.ts -o dist", + "dist": "yarn build && cd dist && zip ../runners.zip index.js", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/jest": "^29.5.12", + "@types/node": "^20.8.9", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "^0.38.1", + "aws-sdk-client-mock": "^3.0.0", + "aws-sdk-client-mock-jest": "^3.0.0", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "jest-mock-extended": "^3.0.6", + "moment-timezone": "^0.5.45", + "nock": "^13.4.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", + "ts-node-dev": "^2.0.0" + }, + "dependencies": { + "@aws-sdk/client-ec2": "^3.604.0", + "@aws-sdk/types": "^3.433.0", + "@middy/core": "^4.7.0", + "@octokit/auth-app": "6.0.3", + "@octokit/rest": "20.0.2", + "@octokit/types": "^13.5.0", + "@terraform-aws-github-runner/aws-powertools-util": "*", + "@terraform-aws-github-runner/aws-ssm-util": "*", + "axios": "^1.6.8", + "cron-parser": "^4.8.1", + "typescript": "^5.4.5" + }, + "nx": { + "includedScripts": [ + "build", + "dist", + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/lambdas/functions/control-plane/src/aws/runners.d.ts b/lambdas/functions/control-plane/src/aws/runners.d.ts new file mode 100644 index 0000000000..ea1f86b735 --- /dev/null +++ b/lambdas/functions/control-plane/src/aws/runners.d.ts @@ -0,0 +1,44 @@ +import { DefaultTargetCapacityType, SpotAllocationStrategy } from '@aws-sdk/client-ec2'; + +export type RunnerType = 'Org' | 'Repo'; + +export interface RunnerList { + instanceId: string; + launchTime?: Date; + owner?: string; + type?: string; + repo?: string; + org?: string; +} + +export interface RunnerInfo { + instanceId: string; + launchTime?: Date; + owner: string; + type: string; +} + +export interface ListRunnerFilters { + runnerType?: RunnerType; + runnerOwner?: string; + environment?: string; + statuses?: string[]; +} + +export interface RunnerInputParameters { + environment: string; + runnerType: RunnerType; + runnerOwner: string; + subnets: string[]; + launchTemplateName: string; + ec2instanceCriteria: { + instanceTypes: string[]; + targetCapacityType: DefaultTargetCapacityType; + maxSpotPrice?: string; + instanceAllocationStrategy: SpotAllocationStrategy; + }; + numberOfRunners: number; + amiIdSsmParameterName?: string; + tracingEnabled?: boolean; + onDemandFailoverOnError?: string[]; +} diff --git a/lambdas/functions/control-plane/src/aws/runners.test.ts b/lambdas/functions/control-plane/src/aws/runners.test.ts new file mode 100644 index 0000000000..d233b16a69 --- /dev/null +++ b/lambdas/functions/control-plane/src/aws/runners.test.ts @@ -0,0 +1,628 @@ +import { + CreateFleetCommand, + CreateFleetCommandInput, + CreateFleetInstance, + CreateFleetResult, + DefaultTargetCapacityType, + DescribeInstancesCommand, + DescribeInstancesResult, + EC2Client, + SpotAllocationStrategy, + TerminateInstancesCommand, +} from '@aws-sdk/client-ec2'; +import { GetParameterCommand, GetParameterResult, PutParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; +import { tracer } from '@terraform-aws-github-runner/aws-powertools-util'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; + +import ScaleError from './../scale-runners/ScaleError'; +import { createRunner, listEC2Runners, terminateRunner } from './runners'; +import { RunnerInfo, RunnerInputParameters, RunnerType } from './runners.d'; + +process.env.AWS_REGION = 'eu-east-1'; +const mockEC2Client = mockClient(EC2Client); +const mockSSMClient = mockClient(SSMClient); + +const LAUNCH_TEMPLATE = 'lt-1'; +const ORG_NAME = 'SomeAwesomeCoder'; +const REPO_NAME = `${ORG_NAME}/some-amazing-library`; +const ENVIRONMENT = 'unit-test-environment'; +const RUNNER_NAME_PREFIX = ''; +const RUNNER_TYPES: RunnerType[] = ['Repo', 'Org']; + +mockEC2Client.on(DescribeInstancesCommand).resolves({}); + +const mockRunningInstances: DescribeInstancesResult = { + Reservations: [ + { + Instances: [ + { + LaunchTime: new Date('2020-10-10T14:48:00.000+09:00'), + InstanceId: 'i-1234', + Tags: [ + { Key: 'ghr:Application', Value: 'github-action-runner' }, + { Key: 'ghr:runner_name_prefix', Value: RUNNER_NAME_PREFIX }, + { Key: 'ghr:created_by', Value: 'scale-up-lambda' }, + { Key: 'ghr:Type', Value: 'Org' }, + { Key: 'ghr:Owner', Value: 'CoderToCat' }, + ], + }, + ], + }, + ], +}; + +describe('list instances', () => { + beforeEach(() => { + jest.resetModules(); + jest.clearAllMocks(); + }); + + it('returns a list of instances', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + const resp = await listEC2Runners(); + expect(resp.length).toBe(1); + expect(resp).toContainEqual({ + instanceId: 'i-1234', + launchTime: new Date('2020-10-10T14:48:00.000+09:00'), + type: 'Org', + owner: 'CoderToCat', + }); + }); + + it('calls EC2 describe instances', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + await listEC2Runners(); + expect(mockEC2Client).toHaveReceivedCommand(DescribeInstancesCommand); + }); + + it('filters instances on repo name', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + await listEC2Runners({ runnerType: 'Repo', runnerOwner: REPO_NAME, environment: undefined }); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeInstancesCommand, { + Filters: [ + { Name: 'instance-state-name', Values: ['running', 'pending'] }, + { Name: 'tag:ghr:Type', Values: ['Repo'] }, + { Name: 'tag:ghr:Owner', Values: [REPO_NAME] }, + { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, + ], + }); + }); + + it('filters instances on org name', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + await listEC2Runners({ runnerType: 'Org', runnerOwner: ORG_NAME, environment: undefined }); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeInstancesCommand, { + Filters: [ + { Name: 'instance-state-name', Values: ['running', 'pending'] }, + { Name: 'tag:ghr:Type', Values: ['Org'] }, + { Name: 'tag:ghr:Owner', Values: [ORG_NAME] }, + { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, + ], + }); + }); + + it('filters instances on environment', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + await listEC2Runners({ environment: ENVIRONMENT }); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeInstancesCommand, { + Filters: [ + { Name: 'instance-state-name', Values: ['running', 'pending'] }, + { Name: 'tag:ghr:environment', Values: [ENVIRONMENT] }, + { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, + ], + }); + }); + + it('No instances, undefined reservations list.', async () => { + const noInstances: DescribeInstancesResult = { + Reservations: undefined, + }; + mockEC2Client.on(DescribeInstancesCommand).resolves(noInstances); + const resp = await listEC2Runners(); + expect(resp.length).toBe(0); + }); + + it('Instances with no tags.', async () => { + const noInstances: DescribeInstancesResult = { + Reservations: [ + { + Instances: [ + { + LaunchTime: new Date('2020-10-11T14:48:00.000+09:00'), + InstanceId: 'i-5678', + Tags: undefined, + }, + ], + }, + ], + }; + mockEC2Client.on(DescribeInstancesCommand).resolves(noInstances); + const resp = await listEC2Runners(); + expect(resp.length).toBe(1); + }); + + it('Filter instances for state running.', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + await listEC2Runners({ statuses: ['running'] }); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeInstancesCommand, { + Filters: [ + { Name: 'instance-state-name', Values: ['running'] }, + { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, + ], + }); + }); + + it('Filter instances with status undefined, fall back to defaults.', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves(mockRunningInstances); + await listEC2Runners({ statuses: undefined }); + expect(mockEC2Client).toHaveReceivedCommandWith(DescribeInstancesCommand, { + Filters: [ + { Name: 'instance-state-name', Values: ['running', 'pending'] }, + { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, + ], + }); + }); +}); + +describe('terminate runner', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('calls terminate instances with the right instance ids', async () => { + mockEC2Client.on(TerminateInstancesCommand).resolves({}); + const runner: RunnerInfo = { + instanceId: 'instance-2', + owner: 'owner-2', + type: 'Repo', + }; + await terminateRunner(runner.instanceId); + + expect(mockEC2Client).toHaveReceivedCommandWith(TerminateInstancesCommand, { InstanceIds: [runner.instanceId] }); + }); +}); + +describe('create runner', () => { + const defaultRunnerConfig: RunnerConfig = { + allocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED, + capacityType: 'spot', + type: 'Org', + }; + + const defaultExpectedFleetRequestValues: ExpectedFleetRequestValues = { + type: 'Org', + capacityType: 'spot', + allocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED, + totalTargetCapacity: 1, + }; + + beforeEach(() => { + jest.clearAllMocks(); + mockEC2Client.reset(); + mockSSMClient.reset(); + + mockEC2Client.on(CreateFleetCommand).resolves({ Instances: [{ InstanceIds: ['i-1234'] }] }); + mockSSMClient.on(GetParameterCommand).resolves({}); + }); + + it.each(RUNNER_TYPES)('calls create fleet of 1 instance with the default config for %p', async (type: RunnerType) => { + await createRunner(createRunnerConfig({ ...defaultRunnerConfig, type: type })); + + expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, { + ...expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, type: type }), + }); + }); + + it('calls create fleet of 2 instances with the correct config for org ', async () => { + const instances = [{ InstanceIds: ['i-1234', 'i-5678'] }]; + + mockEC2Client.on(CreateFleetCommand).resolves({ Instances: instances }); + + await createRunner({ ...createRunnerConfig(defaultRunnerConfig), numberOfRunners: 2 }); + + expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, { + ...expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, totalTargetCapacity: 2 }), + }); + }); + + it('calls create fleet of 1 instance with the on-demand capacity', async () => { + await createRunner(createRunnerConfig({ ...defaultRunnerConfig, capacityType: 'on-demand' })); + expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, { + ...expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, capacityType: 'on-demand' }), + }); + }); + + it('calls run instances with the on-demand capacity', async () => { + await createRunner(createRunnerConfig({ ...defaultRunnerConfig, maxSpotPrice: '0.1' })); + expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, { + ...expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, maxSpotPrice: '0.1' }), + }); + }); + + it('does not create ssm parameters when no instance is created', async () => { + mockEC2Client.on(CreateFleetCommand).resolves({ Instances: [] }); + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toThrowError(Error); + expect(mockSSMClient).not.toHaveReceivedCommand(PutParameterCommand); + }); + + it('uses ami id from ssm parameter when ami id ssm param is specified', async () => { + const paramValue: GetParameterResult = { + Parameter: { + Value: 'ami-123', + }, + }; + mockSSMClient.on(GetParameterCommand).resolves(paramValue); + await createRunner(createRunnerConfig({ ...defaultRunnerConfig, amiIdSsmParameterName: 'my-ami-id-param' })); + const expectedRequest = expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, imageId: 'ami-123' }); + expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, expectedRequest); + expect(mockSSMClient).toHaveReceivedCommandWith(GetParameterCommand, { + Name: 'my-ami-id-param', + }); + }); + it('calls create fleet of 1 instance with runner tracing enabled', async () => { + tracer.getRootXrayTraceId = jest.fn().mockReturnValue('123'); + + await createRunner(createRunnerConfig({ ...defaultRunnerConfig, tracingEnabled: true })); + + expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, { + ...expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, tracingEnabled: true }), + }); + }); +}); + +describe('create runner with errors', () => { + const defaultRunnerConfig: RunnerConfig = { + allocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED, + capacityType: 'spot', + type: 'Repo', + }; + const defaultExpectedFleetRequestValues: ExpectedFleetRequestValues = { + type: 'Repo', + capacityType: 'spot', + allocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED, + totalTargetCapacity: 1, + }; + beforeEach(() => { + jest.clearAllMocks(); + mockEC2Client.reset(); + mockSSMClient.reset(); + + mockSSMClient.on(PutParameterCommand).resolves({}); + mockSSMClient.on(GetParameterCommand).resolves({}); + mockEC2Client.on(CreateFleetCommand).resolves({ Instances: [] }); + }); + + it('test ScaleError with one error.', async () => { + createFleetMockWithErrors(['UnfulfillableCapacity']); + + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(ScaleError); + expect(mockEC2Client).toHaveReceivedCommandWith( + CreateFleetCommand, + expectedCreateFleetRequest(defaultExpectedFleetRequestValues), + ); + expect(mockSSMClient).not.toHaveReceivedCommand(PutParameterCommand); + }); + + it('test ScaleError with multiple error.', async () => { + createFleetMockWithErrors(['UnfulfillableCapacity', 'SomeError']); + + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(ScaleError); + expect(mockEC2Client).toHaveReceivedCommandWith( + CreateFleetCommand, + expectedCreateFleetRequest(defaultExpectedFleetRequestValues), + ); + expect(mockSSMClient).not.toHaveReceivedCommand(PutParameterCommand); + }); + + it('test default Error', async () => { + createFleetMockWithErrors(['NonMappedError']); + + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(Error); + expect(mockEC2Client).toHaveReceivedCommandWith( + CreateFleetCommand, + expectedCreateFleetRequest(defaultExpectedFleetRequestValues), + ); + expect(mockSSMClient).not.toHaveReceivedCommand(PutParameterCommand); + }); + + it('test now error is thrown if an instance is created', async () => { + createFleetMockWithErrors(['NonMappedError'], ['i-123']); + + expect(await createRunner(createRunnerConfig(defaultRunnerConfig))).resolves; + expect(mockEC2Client).toHaveReceivedCommandWith( + CreateFleetCommand, + expectedCreateFleetRequest(defaultExpectedFleetRequestValues), + ); + }); + + it('test error by create fleet call is thrown.', async () => { + mockEC2Client.on(CreateFleetCommand).rejects(new Error('Some error')); + + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(Error); + expect(mockEC2Client).toHaveReceivedCommandWith( + CreateFleetCommand, + expectedCreateFleetRequest(defaultExpectedFleetRequestValues), + ); + expect(mockSSMClient).not.toHaveReceivedCommand(PutParameterCommand); + }); + + it('test error in ami id lookup from ssm parameter', async () => { + mockSSMClient.on(GetParameterCommand).rejects(new Error('Some error')); + + await expect( + createRunner(createRunnerConfig({ ...defaultRunnerConfig, amiIdSsmParameterName: 'my-ami-id-param' })), + ).rejects.toBeInstanceOf(Error); + expect(mockEC2Client).not.toHaveReceivedCommand(CreateFleetCommand); + expect(mockSSMClient).not.toHaveReceivedCommand(PutParameterCommand); + }); + + it('Error with undefined Instances and Errors.', async () => { + mockEC2Client.on(CreateFleetCommand).resolvesOnce({ Instances: undefined, Errors: undefined }); + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(Error); + }); + + it('Error with undefined InstanceIds and ErrorCode.', async () => { + mockEC2Client.on(CreateFleetCommand).resolvesOnce({ + Instances: [{ InstanceIds: undefined }], + Errors: [ + { + ErrorCode: undefined, + }, + ], + }); + await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(Error); + }); +}); + +describe('create runner with errors fail over to OnDemand', () => { + const defaultRunnerConfig: RunnerConfig = { + allocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED, + capacityType: 'spot', + type: 'Repo', + onDemandFailoverOnError: ['InsufficientInstanceCapacity'], + }; + const defaultExpectedFleetRequestValues: ExpectedFleetRequestValues = { + type: 'Repo', + capacityType: 'spot', + allocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED, + totalTargetCapacity: 1, + }; + beforeEach(() => { + jest.clearAllMocks(); + mockEC2Client.reset(); + mockSSMClient.reset(); + + mockSSMClient.on(PutParameterCommand).resolves({}); + mockSSMClient.on(GetParameterCommand).resolves({}); + mockEC2Client.on(CreateFleetCommand).resolves({ Instances: [] }); + }); + + it('test InsufficientInstanceCapacity fallback to on demand .', async () => { + const instancesIds = ['i-123']; + createFleetMockWithWithOnDemandFallback(['InsufficientInstanceCapacity'], instancesIds); + + const instancesResult = await createRunner(createRunnerConfig(defaultRunnerConfig)); + expect(instancesResult).toEqual(instancesIds); + + expect(mockEC2Client).toHaveReceivedCommandTimes(CreateFleetCommand, 2); + + // first call with spot failuer + expect(mockEC2Client).toHaveReceivedNthCommandWith(1, CreateFleetCommand, { + ...expectedCreateFleetRequest({ + ...defaultExpectedFleetRequestValues, + totalTargetCapacity: 1, + capacityType: 'spot', + }), + }); + + // second call with with OnDemand failback + expect(mockEC2Client).toHaveReceivedNthCommandWith(2, CreateFleetCommand, { + ...expectedCreateFleetRequest({ + ...defaultExpectedFleetRequestValues, + totalTargetCapacity: 1, + capacityType: 'on-demand', + }), + }); + }); + + it('test InsufficientInstanceCapacity no failback.', async () => { + await expect( + createRunner(createRunnerConfig({ ...defaultRunnerConfig, onDemandFailoverOnError: [] })), + ).rejects.toBeInstanceOf(Error); + }); + + it('test InsufficientInstanceCapacity with mutlipte instances and fallback to on demand .', async () => { + const instancesIds = ['i-123', 'i-456']; + createFleetMockWithWithOnDemandFallback(['InsufficientInstanceCapacity'], instancesIds); + + const instancesResult = await createRunner({ ...createRunnerConfig(defaultRunnerConfig), numberOfRunners: 2 }); + expect(instancesResult).toEqual(instancesIds); + + expect(mockEC2Client).toHaveReceivedCommandTimes(CreateFleetCommand, 2); + + // first call with spot failuer + expect(mockEC2Client).toHaveReceivedNthCommandWith(1, CreateFleetCommand, { + ...expectedCreateFleetRequest({ + ...defaultExpectedFleetRequestValues, + totalTargetCapacity: 2, + capacityType: 'spot', + }), + }); + + // second call with with OnDemand failback, capacity is reduced by 1 + expect(mockEC2Client).toHaveReceivedNthCommandWith(2, CreateFleetCommand, { + ...expectedCreateFleetRequest({ + ...defaultExpectedFleetRequestValues, + totalTargetCapacity: 1, + capacityType: 'on-demand', + }), + }); + }); + + it('test UnfulfillableCapacity with mutlipte instances and no fallback to on demand .', async () => { + const instancesIds = ['i-123', 'i-456']; + // fallback to on demand for UnfulfillableCapacity but InsufficientInstanceCapacity is thrown + createFleetMockWithWithOnDemandFallback(['UnfulfillableCapacity'], instancesIds); + + await expect( + createRunner({ ...createRunnerConfig(defaultRunnerConfig), numberOfRunners: 2 }), + ).rejects.toBeInstanceOf(Error); + + expect(mockEC2Client).toHaveReceivedCommandTimes(CreateFleetCommand, 1); + + // first call with spot failuer + expect(mockEC2Client).toHaveReceivedNthCommandWith(1, CreateFleetCommand, { + ...expectedCreateFleetRequest({ + ...defaultExpectedFleetRequestValues, + totalTargetCapacity: 2, + capacityType: 'spot', + }), + }); + }); +}); + +function createFleetMockWithErrors(errors: string[], instances?: string[]) { + let result: CreateFleetResult = { + Errors: errors.map((e) => ({ ErrorCode: e })), + }; + + if (instances) { + result = { + ...result, + Instances: [ + { + InstanceIds: instances.map((i) => i), + }, + ], + }; + } + + mockEC2Client.on(CreateFleetCommand).resolves(result); +} + +function createFleetMockWithWithOnDemandFallback(errors: string[], instances?: string[], numberOfFailures = 1) { + const instanceesFirstCall: CreateFleetInstance = { + InstanceIds: instances?.slice(0, instances.length - numberOfFailures).map((i) => i), + }; + + const instancesSecondCall: CreateFleetInstance = { + InstanceIds: instances?.slice(instances.length - numberOfFailures, instances.length).map((i) => i), + }; + + mockEC2Client + .on(CreateFleetCommand) + .resolvesOnce({ Instances: [instanceesFirstCall], Errors: errors.map((e) => ({ ErrorCode: e })) }) + .resolvesOnce({ Instances: [instancesSecondCall] }); +} + +interface RunnerConfig { + type: RunnerType; + capacityType: DefaultTargetCapacityType; + allocationStrategy: SpotAllocationStrategy; + maxSpotPrice?: string; + amiIdSsmParameterName?: string; + tracingEnabled?: boolean; + onDemandFailoverOnError?: string[]; +} + +function createRunnerConfig(runnerConfig: RunnerConfig): RunnerInputParameters { + return { + environment: ENVIRONMENT, + runnerType: runnerConfig.type, + runnerOwner: REPO_NAME, + numberOfRunners: 1, + launchTemplateName: LAUNCH_TEMPLATE, + ec2instanceCriteria: { + instanceTypes: ['m5.large', 'c5.large'], + targetCapacityType: runnerConfig.capacityType, + maxSpotPrice: runnerConfig.maxSpotPrice, + instanceAllocationStrategy: runnerConfig.allocationStrategy, + }, + subnets: ['subnet-123', 'subnet-456'], + amiIdSsmParameterName: runnerConfig.amiIdSsmParameterName, + tracingEnabled: runnerConfig.tracingEnabled, + onDemandFailoverOnError: runnerConfig.onDemandFailoverOnError, + }; +} + +interface ExpectedFleetRequestValues { + type: 'Repo' | 'Org'; + capacityType: DefaultTargetCapacityType; + allocationStrategy: SpotAllocationStrategy; + maxSpotPrice?: string; + totalTargetCapacity: number; + imageId?: string; + tracingEnabled?: boolean; +} + +function expectedCreateFleetRequest(expectedValues: ExpectedFleetRequestValues): CreateFleetCommandInput { + const tags = [ + { Key: 'ghr:Application', Value: 'github-action-runner' }, + { Key: 'ghr:created_by', Value: expectedValues.totalTargetCapacity > 1 ? 'pool-lambda' : 'scale-up-lambda' }, + { Key: 'ghr:Type', Value: expectedValues.type }, + { Key: 'ghr:Owner', Value: REPO_NAME }, + ]; + if (expectedValues.tracingEnabled) { + const traceId = tracer.getRootXrayTraceId(); + tags.push({ Key: 'ghr:trace_id', Value: traceId! }); + } + const request: CreateFleetCommandInput = { + LaunchTemplateConfigs: [ + { + LaunchTemplateSpecification: { + LaunchTemplateName: 'lt-1', + Version: '$Default', + }, + Overrides: [ + { + InstanceType: 'm5.large', + SubnetId: 'subnet-123', + }, + { + InstanceType: 'c5.large', + SubnetId: 'subnet-123', + }, + { + InstanceType: 'm5.large', + SubnetId: 'subnet-456', + }, + { + InstanceType: 'c5.large', + SubnetId: 'subnet-456', + }, + ], + }, + ], + SpotOptions: { + AllocationStrategy: expectedValues.allocationStrategy, + MaxTotalPrice: expectedValues.maxSpotPrice, + }, + TagSpecifications: [ + { + ResourceType: 'instance', + Tags: tags, + }, + { + ResourceType: 'volume', + Tags: tags, + }, + ], + TargetCapacitySpecification: { + DefaultTargetCapacityType: expectedValues.capacityType, + TotalTargetCapacity: expectedValues.totalTargetCapacity, + }, + Type: 'instant', + }; + + if (expectedValues.imageId) { + for (const config of request?.LaunchTemplateConfigs ?? []) { + if (config.Overrides) { + for (const override of config.Overrides) { + override.ImageId = expectedValues.imageId; + } + } + } + } + + return request; +} diff --git a/lambdas/functions/control-plane/src/aws/runners.ts b/lambdas/functions/control-plane/src/aws/runners.ts new file mode 100644 index 0000000000..889d3c5f8a --- /dev/null +++ b/lambdas/functions/control-plane/src/aws/runners.ts @@ -0,0 +1,285 @@ +import { + CreateFleetCommand, + CreateFleetResult, + DescribeInstancesCommand, + DescribeInstancesResult, + EC2Client, + FleetLaunchTemplateOverridesRequest, + TerminateInstancesCommand, + _InstanceType, +} from '@aws-sdk/client-ec2'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getTracedAWSV3Client, tracer } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; +import moment from 'moment'; + +import ScaleError from './../scale-runners/ScaleError'; +import * as Runners from './runners.d'; + +const logger = createChildLogger('runners'); + +interface Ec2Filter { + Name: string; + Values: string[]; +} + +export async function listEC2Runners( + filters: Runners.ListRunnerFilters | undefined = undefined, +): Promise { + const ec2Filters = constructFilters(filters); + const runners: Runners.RunnerList[] = []; + for (const filter of ec2Filters) { + runners.push(...(await getRunners(filter))); + } + return runners; +} + +function constructFilters(filters?: Runners.ListRunnerFilters): Ec2Filter[][] { + const ec2Statuses = filters?.statuses ? filters.statuses : ['running', 'pending']; + const ec2Filters: Ec2Filter[][] = []; + const ec2FiltersBase = [{ Name: 'instance-state-name', Values: ec2Statuses }]; + if (filters) { + if (filters.environment !== undefined) { + ec2FiltersBase.push({ Name: 'tag:ghr:environment', Values: [filters.environment] }); + } + if (filters.runnerType && filters.runnerOwner) { + ec2FiltersBase.push({ Name: `tag:ghr:Type`, Values: [filters.runnerType] }); + ec2FiltersBase.push({ Name: `tag:ghr:Owner`, Values: [filters.runnerOwner] }); + } + } + + for (const key of ['tag:ghr:Application']) { + const filter = [...ec2FiltersBase]; + filter.push({ Name: key, Values: ['github-action-runner'] }); + ec2Filters.push(filter); + } + return ec2Filters; +} + +async function getRunners(ec2Filters: Ec2Filter[]): Promise { + const ec2 = getTracedAWSV3Client(new EC2Client({ region: process.env.AWS_REGION })); + const runners: Runners.RunnerList[] = []; + let nextToken; + let hasNext = true; + while (hasNext) { + const instances: DescribeInstancesResult = await ec2.send( + new DescribeInstancesCommand({ Filters: ec2Filters, NextToken: nextToken }), + ); + hasNext = instances.NextToken ? true : false; + nextToken = instances.NextToken; + runners.push(...getRunnerInfo(instances)); + } + return runners; +} + +function getRunnerInfo(runningInstances: DescribeInstancesResult) { + const runners: Runners.RunnerList[] = []; + if (runningInstances.Reservations) { + for (const r of runningInstances.Reservations) { + if (r.Instances) { + for (const i of r.Instances) { + runners.push({ + instanceId: i.InstanceId as string, + launchTime: i.LaunchTime, + owner: i.Tags?.find((e) => e.Key === 'ghr:Owner')?.Value as string, + type: i.Tags?.find((e) => e.Key === 'ghr:Type')?.Value as string, + repo: i.Tags?.find((e) => e.Key === 'ghr:Repo')?.Value as string, + org: i.Tags?.find((e) => e.Key === 'ghr:Org')?.Value as string, + }); + } + } + } + } + return runners; +} + +export async function terminateRunner(instanceId: string): Promise { + logger.info(`Runner '${instanceId}' will be terminated.`); + const ec2 = getTracedAWSV3Client(new EC2Client({ region: process.env.AWS_REGION })); + await ec2.send(new TerminateInstancesCommand({ InstanceIds: [instanceId] })); + logger.info(`Runner ${instanceId} has been terminated.`); +} + +function generateFleetOverrides( + subnetIds: string[], + instancesTypes: string[], + amiId?: string, +): FleetLaunchTemplateOverridesRequest[] { + const result: FleetLaunchTemplateOverridesRequest[] = []; + subnetIds.forEach((s) => { + instancesTypes.forEach((i) => { + const item: FleetLaunchTemplateOverridesRequest = { + SubnetId: s, + InstanceType: i as _InstanceType, + ImageId: amiId, + }; + result.push(item); + }); + }); + return result; +} + +export async function createRunner(runnerParameters: Runners.RunnerInputParameters): Promise { + logger.debug('Runner configuration.', { + runner: { + configuration: { + ...runnerParameters, + }, + }, + }); + + const ec2Client = getTracedAWSV3Client(new EC2Client({ region: process.env.AWS_REGION })); + const amiIdOverride = await getAmiIdOverride(runnerParameters); + + const fleet: CreateFleetResult = await createInstances(runnerParameters, amiIdOverride, ec2Client); + + const instances: string[] = await processFleetResult(fleet, runnerParameters); + + logger.info(`Created instance(s): ${instances.join(',')}`); + + return instances; +} + +async function processFleetResult( + fleet: CreateFleetResult, + runnerParameters: Runners.RunnerInputParameters, +): Promise { + const instances: string[] = fleet.Instances?.flatMap((i) => i.InstanceIds?.flatMap((j) => j) || []) || []; + + if (instances.length !== runnerParameters.numberOfRunners) { + logger.warn( + `${ + instances.length === 0 ? 'No' : instances.length + ' off ' + runnerParameters.numberOfRunners + } instances created.`, + { data: fleet }, + ); + const errors = fleet.Errors?.flatMap((e) => e.ErrorCode || '') || []; + + // Educated guess of errors that would make sense to retry based on the list + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html + const scaleErrors = [ + 'UnfulfillableCapacity', + 'MaxSpotInstanceCountExceeded', + 'TargetCapacityLimitExceededException', + 'RequestLimitExceeded', + 'ResourceLimitExceeded', + 'MaxSpotInstanceCountExceeded', + 'MaxSpotFleetRequestCountExceeded', + 'InsufficientInstanceCapacity', + ]; + + if ( + errors.some((e) => runnerParameters.onDemandFailoverOnError?.includes(e)) && + runnerParameters.ec2instanceCriteria.targetCapacityType === 'spot' + ) { + logger.warn(`Create fleet failed, initatiing fall back to on demand instances.`); + logger.debug('Create fleet failed.', { data: fleet.Errors }); + const numberOfInstances = runnerParameters.numberOfRunners - instances.length; + const instancesOnDemand = await createRunner({ + ...runnerParameters, + numberOfRunners: numberOfInstances, + onDemandFailoverOnError: ['InsufficientInstanceCapacity'], + ec2instanceCriteria: { ...runnerParameters.ec2instanceCriteria, targetCapacityType: 'on-demand' }, + }); + instances.push(...instancesOnDemand); + return instances; + } else if (errors.some((e) => scaleErrors.includes(e))) { + logger.warn('Create fleet failed, ScaleError will be thrown to trigger retry for ephemeral runners.'); + logger.debug('Create fleet failed.', { data: fleet.Errors }); + throw new ScaleError('Failed to create instance, create fleet failed.'); + } else { + logger.warn('Create fleet failed, error not recognized as scaling error.', { data: fleet.Errors }); + throw Error('Create fleet failed, no instance created.'); + } + } + return instances; +} + +async function getAmiIdOverride(runnerParameters: Runners.RunnerInputParameters): Promise { + if (!runnerParameters.amiIdSsmParameterName) { + return undefined; + } + + try { + const amiIdOverride = await getParameter(runnerParameters.amiIdSsmParameterName); + logger.debug(`AMI override SSM parameter (${runnerParameters.amiIdSsmParameterName}) set to: ${amiIdOverride}`); + return amiIdOverride; + } catch (e) { + logger.debug( + `Failed to lookup runner AMI ID from SSM parameter: ${runnerParameters.amiIdSsmParameterName}. ` + + 'Please ensure that the given parameter exists on this region and contains a valid runner AMI ID', + { error: e }, + ); + throw new Error(`Failed to lookup runner AMI ID from SSM parameter: ${runnerParameters.amiIdSsmParameterName}, + ${e}`); + } +} + +async function createInstances( + runnerParameters: Runners.RunnerInputParameters, + amiIdOverride: string | undefined, + ec2Client: EC2Client, +) { + const tags = [ + { Key: 'ghr:Application', Value: 'github-action-runner' }, + { Key: 'ghr:created_by', Value: runnerParameters.numberOfRunners === 1 ? 'scale-up-lambda' : 'pool-lambda' }, + { Key: 'ghr:Type', Value: runnerParameters.runnerType }, + { Key: 'ghr:Owner', Value: runnerParameters.runnerOwner }, + ]; + + if (runnerParameters.tracingEnabled) { + const traceId = tracer.getRootXrayTraceId(); + tags.push({ Key: 'ghr:trace_id', Value: traceId! }); + } + + let fleet: CreateFleetResult; + try { + // see for spec https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html + const createFleetCommand = new CreateFleetCommand({ + LaunchTemplateConfigs: [ + { + LaunchTemplateSpecification: { + LaunchTemplateName: runnerParameters.launchTemplateName, + Version: '$Default', + }, + Overrides: generateFleetOverrides( + runnerParameters.subnets, + runnerParameters.ec2instanceCriteria.instanceTypes, + amiIdOverride, + ), + }, + ], + SpotOptions: { + MaxTotalPrice: runnerParameters.ec2instanceCriteria.maxSpotPrice, + AllocationStrategy: runnerParameters.ec2instanceCriteria.instanceAllocationStrategy, + }, + TargetCapacitySpecification: { + TotalTargetCapacity: runnerParameters.numberOfRunners, + DefaultTargetCapacityType: runnerParameters.ec2instanceCriteria.targetCapacityType, + }, + TagSpecifications: [ + { + ResourceType: 'instance', + Tags: tags, + }, + { + ResourceType: 'volume', + Tags: tags, + }, + ], + Type: 'instant', + }); + fleet = await ec2Client.send(createFleetCommand); + } catch (e) { + logger.warn('Create fleet request failed.', { error: e as Error }); + throw e; + } + return fleet; +} + +// If launchTime is undefined, this will return false +export function bootTimeExceeded(ec2Runner: { launchTime?: Date }): boolean { + const runnerBootTimeInMinutes = process.env.RUNNER_BOOT_TIME_IN_MINUTES; + const launchTimePlusBootTime = moment(ec2Runner.launchTime).utc().add(runnerBootTimeInMinutes, 'minutes'); + return launchTimePlusBootTime < moment(new Date()).utc(); +} diff --git a/lambdas/functions/control-plane/src/axios/fetch-override.test.ts b/lambdas/functions/control-plane/src/axios/fetch-override.test.ts new file mode 100644 index 0000000000..e19c0c1f89 --- /dev/null +++ b/lambdas/functions/control-plane/src/axios/fetch-override.test.ts @@ -0,0 +1,31 @@ +import axios, { AxiosResponse } from 'axios'; + +import { axiosFetch } from './fetch-override'; + +jest.mock('axios'); +type FetchResponse = AxiosResponse & { json: () => string }; + +describe('axiosFetch', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + it('should return a promise that resolves with the response data', async () => { + // Arrange + const url = 'https://example.com'; + const options = { body: { foo: 'bar' } }; + const responseData = { data: { baz: 'qux' } }; + const mockedAxios = axios as unknown as jest.Mock; + mockedAxios.mockResolvedValue(responseData); + + // Act + const result = (await axiosFetch(url, options)) as FetchResponse; + + // Assert + expect(axios).toHaveBeenCalledWith(url, { ...options, data: options.body }); + expect(result).toEqual({ + ...responseData, + json: expect.any(Function), + }); + expect(result.json()).toEqual(responseData.data); + }); +}); diff --git a/lambdas/functions/control-plane/src/axios/fetch-override.ts b/lambdas/functions/control-plane/src/axios/fetch-override.ts new file mode 100644 index 0000000000..fe15054d20 --- /dev/null +++ b/lambdas/functions/control-plane/src/axios/fetch-override.ts @@ -0,0 +1,19 @@ +import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; + +type FetchResponse = AxiosResponse & { json: () => string }; + +type FetchOptions = AxiosRequestConfig & { body?: object }; + +// Fetch is not covered to be traced by xray so we need to override it with axios +// https://github.com/aws/aws-xray-sdk-node/issues/531 +export const axiosFetch = async (url: string, options: FetchOptions): Promise => { + const response = await axios(url, { ...options, data: options.body }); + return new Promise((resolve) => { + resolve({ + ...response, + json: () => { + return response.data; + }, + }); + }); +}; diff --git a/modules/runners/lambdas/runners/src/gh-auth/gh-auth.test.ts b/lambdas/functions/control-plane/src/gh-auth/gh-auth.test.ts similarity index 88% rename from modules/runners/lambdas/runners/src/gh-auth/gh-auth.test.ts rename to lambdas/functions/control-plane/src/gh-auth/gh-auth.test.ts index 2c6510363a..584f0d6b8d 100644 --- a/modules/runners/lambdas/runners/src/gh-auth/gh-auth.test.ts +++ b/lambdas/functions/control-plane/src/gh-auth/gh-auth.test.ts @@ -2,14 +2,14 @@ import { createAppAuth } from '@octokit/auth-app'; import { StrategyOptions } from '@octokit/auth-app/dist-types/types'; import { request } from '@octokit/request'; import { RequestInterface } from '@octokit/types'; +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; import { mocked } from 'jest-mock'; import { MockProxy, mock } from 'jest-mock-extended'; import nock from 'nock'; -import { getParameterValue } from './../aws/ssm'; import { createGithubAppAuth, createOctoClient } from './gh-auth'; -jest.mock('./../aws/ssm'); +jest.mock('@terraform-aws-github-runner/aws-ssm-util'); jest.mock('@octokit/auth-app'); const cleanEnv = process.env; @@ -18,7 +18,7 @@ const GITHUB_APP_ID = '1'; const PARAMETER_GITHUB_APP_ID_NAME = `/actions-runner/${ENVIRONMENT}/github_app_id`; const PARAMETER_GITHUB_APP_KEY_BASE64_NAME = `/actions-runner/${ENVIRONMENT}/github_app_key_base64`; -const mockedGet = mocked(getParameterValue); +const mockedGet = mocked(getParameter); beforeEach(() => { jest.resetModules(); @@ -95,7 +95,7 @@ ${decryptedValue}`, // Assert expect(mockedCreatAppAuth).toBeCalledTimes(1); - expect(mockedCreatAppAuth).toBeCalledWith(authOptions); + expect(mockedCreatAppAuth).toBeCalledWith({ ...authOptions, request: expect.anything() }); }); test('Creates auth object for public GitHub', async () => { @@ -117,11 +117,11 @@ ${decryptedValue}`, const result = await createGithubAppAuth(installationId); // Assert - expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME); - expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME); + expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME); + expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME); expect(mockedCreatAppAuth).toBeCalledTimes(1); - expect(mockedCreatAppAuth).toBeCalledWith(authOptions); + expect(mockedCreatAppAuth).toBeCalledWith({ ...authOptions, request: expect.anything() }); expect(mockedAuth).toBeCalledWith({ type: authType }); expect(result.token).toBe(token); }); @@ -154,8 +154,8 @@ ${decryptedValue}`, const result = await createGithubAppAuth(installationId, githubServerUrl); // Assert - expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME); - expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME); + expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME); + expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME); expect(mockedCreatAppAuth).toBeCalledTimes(1); expect(mockedCreatAppAuth).toBeCalledWith(authOptions); @@ -191,8 +191,8 @@ ${decryptedValue}`, const result = await createGithubAppAuth(installationId, githubServerUrl); // Assert - expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME); - expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME); + expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME); + expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME); expect(mockedCreatAppAuth).toBeCalledTimes(1); expect(mockedCreatAppAuth).toBeCalledWith(authOptions); diff --git a/modules/runners/lambdas/runners/src/gh-auth/gh-auth.ts b/lambdas/functions/control-plane/src/gh-auth/gh-auth.ts similarity index 76% rename from modules/runners/lambdas/runners/src/gh-auth/gh-auth.ts rename to lambdas/functions/control-plane/src/gh-auth/gh-auth.ts index 93ff477fe1..ae00775991 100644 --- a/modules/runners/lambdas/runners/src/gh-auth/gh-auth.ts +++ b/lambdas/functions/control-plane/src/gh-auth/gh-auth.ts @@ -10,15 +10,16 @@ import { import { OctokitOptions } from '@octokit/core/dist-types/types'; import { request } from '@octokit/request'; import { Octokit } from '@octokit/rest'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; -import { getParameterValue } from '../aws/ssm'; -import { LogFields, logger as rootLogger } from '../logger'; - -const logger = rootLogger.getChildLogger({ name: 'gh-auth' }); +import { axiosFetch } from '../axios/fetch-override'; +const logger = createChildLogger('gh-auth'); export async function createOctoClient(token: string, ghesApiUrl = ''): Promise { const ocktokitOptions: OctokitOptions = { auth: token, + request: { fetch: axiosFetch }, }; if (ghesApiUrl) { ocktokitOptions.baseUrl = ghesApiUrl; @@ -46,11 +47,11 @@ export async function createGithubInstallationAuth( } async function createAuth(installationId: number | undefined, ghesApiUrl: string): Promise { - const appId = parseInt(await getParameterValue(process.env.PARAMETER_GITHUB_APP_ID_NAME)); + const appId = parseInt(await getParameter(process.env.PARAMETER_GITHUB_APP_ID_NAME)); let authOptions: StrategyOptions = { appId, privateKey: Buffer.from( - await getParameterValue(process.env.PARAMETER_GITHUB_APP_KEY_BASE64_NAME), + await getParameter(process.env.PARAMETER_GITHUB_APP_KEY_BASE64_NAME), 'base64', // replace literal \n characters with new lines to allow the key to be stored as a // single line variable. This logic should match how the GitHub Terraform provider @@ -61,11 +62,16 @@ async function createAuth(installationId: number | undefined, ghesApiUrl: string }; if (installationId) authOptions = { ...authOptions, installationId }; - logger.debug(`GHES API URL: ${ghesApiUrl}`, LogFields.print()); + logger.debug(`GHES API URL: ${ghesApiUrl}`); if (ghesApiUrl) { authOptions.request = request.defaults({ baseUrl: ghesApiUrl, + request: { + fetch: axiosFetch, + }, }); + } else { + authOptions.request = request.defaults({ request: { fetch: axiosFetch } }); } return createAppAuth(authOptions); } diff --git a/modules/runners/lambdas/runners/src/lambda.test.ts b/lambdas/functions/control-plane/src/lambda.test.ts similarity index 65% rename from modules/runners/lambdas/runners/src/lambda.test.ts rename to lambdas/functions/control-plane/src/lambda.test.ts index 8fa3b9a6c5..f4d28ccd79 100644 --- a/modules/runners/lambdas/runners/src/lambda.test.ts +++ b/lambdas/functions/control-plane/src/lambda.test.ts @@ -1,12 +1,13 @@ +import { captureLambdaHandler, logger } from '@terraform-aws-github-runner/aws-powertools-util'; import { Context, SQSEvent, SQSRecord } from 'aws-lambda'; import { mocked } from 'jest-mock'; -import { adjustPool, scaleDownHandler, scaleUpHandler } from './lambda'; -import { logger } from './logger'; +import { addMiddleware, adjustPool, scaleDownHandler, scaleUpHandler, ssmHousekeeper } from './lambda'; import { adjust } from './pool/pool'; import ScaleError from './scale-runners/ScaleError'; import { scaleDown } from './scale-runners/scale-down'; import { ActionRequestMessage, scaleUp } from './scale-runners/scale-up'; +import { cleanSSMTokens } from './scale-runners/ssm-housekeeper'; const body: ActionRequestMessage = { eventType: 'workflow_job', @@ -61,7 +62,9 @@ const context: Context = { jest.mock('./scale-runners/scale-up'); jest.mock('./scale-runners/scale-down'); jest.mock('./pool/pool'); -jest.mock('./logger'); +jest.mock('./scale-runners/ssm-housekeeper'); +jest.mock('@terraform-aws-github-runner/aws-powertools-util'); +jest.mock('@terraform-aws-github-runner/aws-ssm-util'); // Docs for testing async with jest: https://jestjs.io/docs/tutorial-async describe('Test scale up lambda wrapper.', () => { @@ -87,7 +90,7 @@ describe('Test scale up lambda wrapper.', () => { const error = new Error('Non scale should resolve.'); const mock = mocked(scaleUp); mock.mockRejectedValue(error); - await expect(scaleUpHandler(sqsEvent, context)).resolves; + await expect(scaleUpHandler(sqsEvent, context)).resolves.not.toThrow; }); it('Scale should be rejected', async () => { @@ -110,11 +113,12 @@ async function testInvalidRecords(sqsRecords: SQSRecord[]) { Records: sqsRecords, }; - await expect(scaleUpHandler(sqsEventMultipleRecords, context)).resolves; + await expect(scaleUpHandler(sqsEventMultipleRecords, context)).resolves.not.toThrow(); expect(logWarnSpy).toHaveBeenCalledWith( - 'Event ignored, only one record at the time can be handled, ensure the lambda batch size is set to 1.', - undefined, + expect.stringContaining( + 'Event ignored, only one record at the time can be handled, ensure the lambda batch size is set to 1.', + ), ); } @@ -126,14 +130,14 @@ describe('Test scale down lambda wrapper.', () => { resolve(); }); }); - await expect(scaleDownHandler(context)).resolves; + await expect(scaleDownHandler({}, context)).resolves.not.toThrow(); }); it('Scaling down with error.', async () => { const error = new Error('Scaling down with error.'); const mock = mocked(scaleDown); mock.mockRejectedValue(error); - await expect(await scaleDownHandler(context)).resolves; + await expect(scaleDownHandler({}, context)).resolves.not.toThrow(); }); }); @@ -145,7 +149,7 @@ describe('Adjust pool.', () => { resolve(); }); }); - await expect(adjustPool({ poolSize: 2 }, context)).resolves; + await expect(adjustPool({ poolSize: 2 }, context)).resolves.not.toThrow(); }); it('Handle error for adjusting pool.', async () => { @@ -154,6 +158,39 @@ describe('Adjust pool.', () => { mock.mockRejectedValue(error); const logSpy = jest.spyOn(logger, 'error'); await adjustPool({ poolSize: 0 }, context); - expect(logSpy).lastCalledWith(error); + expect(logSpy).lastCalledWith(expect.stringContaining(error.message), expect.anything()); + }); +}); + +describe('Test middleware', () => { + it('Should have a working middleware', async () => { + const mockedLambdaHandler = captureLambdaHandler as unknown as jest.Mock; + mockedLambdaHandler.mockReturnValue({ before: jest.fn(), after: jest.fn(), onError: jest.fn() }); + expect(addMiddleware).not.toThrowError(); + }); +}); + +describe('Test ssm housekeeper lambda wrapper.', () => { + it('Invoke without errors.', async () => { + const mock = mocked(cleanSSMTokens); + mock.mockImplementation(() => { + return new Promise((resolve) => { + resolve(); + }); + }); + + process.env.SSM_CLEANUP_CONFIG = JSON.stringify({ + dryRun: false, + minimumDaysOld: 1, + tokenPath: '/path/to/tokens/', + }); + + await expect(ssmHousekeeper({}, context)).resolves.not.toThrow(); + }); + + it('Errors not throwed.', async () => { + const mock = mocked(cleanSSMTokens); + mock.mockRejectedValue(new Error()); + await expect(ssmHousekeeper({}, context)).resolves.not.toThrow(); }); }); diff --git a/lambdas/functions/control-plane/src/lambda.ts b/lambdas/functions/control-plane/src/lambda.ts new file mode 100644 index 0000000000..0389483285 --- /dev/null +++ b/lambdas/functions/control-plane/src/lambda.ts @@ -0,0 +1,76 @@ +import middy from '@middy/core'; +import { logger, setContext } from '@terraform-aws-github-runner/aws-powertools-util'; +import { captureLambdaHandler, tracer } from '@terraform-aws-github-runner/aws-powertools-util'; +import { Context, SQSEvent } from 'aws-lambda'; + +import { PoolEvent, adjust } from './pool/pool'; +import ScaleError from './scale-runners/ScaleError'; +import { scaleDown } from './scale-runners/scale-down'; +import { scaleUp } from './scale-runners/scale-up'; +import { SSMCleanupOptions, cleanSSMTokens } from './scale-runners/ssm-housekeeper'; + +export async function scaleUpHandler(event: SQSEvent, context: Context): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + + if (event.Records.length !== 1) { + logger.warn('Event ignored, only one record at the time can be handled, ensure the lambda batch size is set to 1.'); + return new Promise((resolve) => resolve()); + } + + try { + await scaleUp(event.Records[0].eventSource, JSON.parse(event.Records[0].body)); + } catch (e) { + if (e instanceof ScaleError) { + throw e; + } else { + logger.warn(`Ignoring error: ${e}`); + } + } +} + +export async function scaleDownHandler(event: unknown, context: Context): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + + try { + await scaleDown(); + } catch (e) { + logger.error(`${(e as Error).message}`, { error: e as Error }); + } +} + +export async function adjustPool(event: PoolEvent, context: Context): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + + try { + await adjust(event); + } catch (e) { + logger.error(`${(e as Error).message}`, { error: e as Error }); + } +} + +export const addMiddleware = () => { + const handler = captureLambdaHandler(tracer); + if (!handler) { + return; + } + middy(scaleUpHandler).use(handler); + middy(scaleDownHandler).use(handler); + middy(adjustPool).use(handler); + middy(ssmHousekeeper).use(handler); +}; +addMiddleware(); + +export async function ssmHousekeeper(event: unknown, context: Context): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + const config = JSON.parse(process.env.SSM_CLEANUP_CONFIG) as SSMCleanupOptions; + + try { + await cleanSSMTokens(config); + } catch (e) { + logger.error(`${(e as Error).message}`, { error: e as Error }); + } +} diff --git a/modules/runners/lambdas/runners/src/local-down.ts b/lambdas/functions/control-plane/src/local-down.ts similarity index 100% rename from modules/runners/lambdas/runners/src/local-down.ts rename to lambdas/functions/control-plane/src/local-down.ts diff --git a/modules/runners/lambdas/runners/src/local-pool.ts b/lambdas/functions/control-plane/src/local-pool.ts similarity index 100% rename from modules/runners/lambdas/runners/src/local-pool.ts rename to lambdas/functions/control-plane/src/local-pool.ts diff --git a/lambdas/functions/control-plane/src/local-ssm-housekeeper.ts b/lambdas/functions/control-plane/src/local-ssm-housekeeper.ts new file mode 100644 index 0000000000..ec635b13ad --- /dev/null +++ b/lambdas/functions/control-plane/src/local-ssm-housekeeper.ts @@ -0,0 +1,15 @@ +import { cleanSSMTokens } from './scale-runners/ssm-housekeeper'; + +export function run(): void { + cleanSSMTokens({ + dryRun: true, + minimumDaysOld: 3, + tokenPath: '/ghr/my-env/runners/tokens', + }) + .then() + .catch((e) => { + console.log(e); + }); +} + +run(); diff --git a/modules/runners/lambdas/runners/src/local.ts b/lambdas/functions/control-plane/src/local.ts similarity index 95% rename from modules/runners/lambdas/runners/src/local.ts rename to lambdas/functions/control-plane/src/local.ts index 5c79110d76..ac744219c1 100644 --- a/modules/runners/lambdas/runners/src/local.ts +++ b/lambdas/functions/control-plane/src/local.ts @@ -1,4 +1,5 @@ -import { logger } from './logger'; +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; + import { ActionRequestMessage, scaleUp } from './scale-runners/scale-up'; const sqsEvent = { diff --git a/modules/runners/lambdas/runners/src/modules.d.ts b/lambdas/functions/control-plane/src/modules.d.ts similarity index 86% rename from modules/runners/lambdas/runners/src/modules.d.ts rename to lambdas/functions/control-plane/src/modules.d.ts index 41d4339c1e..38e1186bf0 100644 --- a/modules/runners/lambdas/runners/src/modules.d.ts +++ b/lambdas/functions/control-plane/src/modules.d.ts @@ -1,6 +1,7 @@ declare namespace NodeJS { export interface ProcessEnv { AWS_REGION: string; + ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS: string; ENVIRONMENT: string; GHES_URL: string; LAUNCH_TEMPLATE_NAME: string; @@ -13,12 +14,15 @@ declare namespace NodeJS { PARAMETER_GITHUB_APP_KEY_BASE64_NAME: string; RUNNER_OWNER: string; SCALE_DOWN_CONFIG: string; + SSM_TOKEN_PATH: string; + SSM_CLEANUP_CONFIG: string; SUBNET_IDS: string; INSTANCE_TYPES: string; INSTANCE_TARGET_CAPACITY_TYPE: 'on-demand' | 'spot'; INSTANCE_MAX_SPOT_PRICE: string | undefined; INSTANCE_ALLOCATION_STRATEGY: | 'lowest-price' + | 'price-capacity-optimized' | 'diversified' | 'capacity-optimized' | 'capacity-optimized-prioritized'; diff --git a/lambdas/functions/control-plane/src/pool/pool.test.ts b/lambdas/functions/control-plane/src/pool/pool.test.ts new file mode 100644 index 0000000000..fabcb47c23 --- /dev/null +++ b/lambdas/functions/control-plane/src/pool/pool.test.ts @@ -0,0 +1,310 @@ +import { Octokit } from '@octokit/rest'; +import { mocked } from 'jest-mock'; +import moment from 'moment-timezone'; +import nock from 'nock'; + +import { listEC2Runners } from '../aws/runners'; +import * as ghAuth from '../gh-auth/gh-auth'; +import { createRunners } from '../scale-runners/scale-up'; +import { adjust } from './pool'; + +const mockOctokit = { + paginate: jest.fn(), + checks: { get: jest.fn() }, + actions: { + createRegistrationTokenForOrg: jest.fn(), + }, + apps: { + getOrgInstallation: jest.fn(), + }, +}; + +jest.mock('@octokit/rest', () => ({ + Octokit: jest.fn().mockImplementation(() => mockOctokit), +})); + +jest.mock('./../aws/runners', () => ({ + ...jest.requireActual('./../aws/runners'), + listEC2Runners: jest.fn(), +})); +jest.mock('./../gh-auth/gh-auth'); +jest.mock('./../scale-runners/scale-up'); + +const mocktokit = Octokit as jest.MockedClass; +const mockedAppAuth = mocked(ghAuth.createGithubAppAuth, { + shallow: false, +}); +const mockedInstallationAuth = mocked(ghAuth.createGithubInstallationAuth, { shallow: false }); +const mockCreateClient = mocked(ghAuth.createOctoClient, { shallow: false }); +const mockListRunners = mocked(listEC2Runners); + +const cleanEnv = process.env; + +const ORG = 'my-org'; +const MINIMUM_TIME_RUNNING = 15; + +const ec2InstancesRegistered = [ + { + instanceId: 'i-1-idle', + launchTime: new Date(), + type: 'Org', + owner: ORG, + }, + { + instanceId: 'i-2-busy', + launchTime: new Date(), + type: 'Org', + owner: ORG, + }, + { + instanceId: 'i-3-offline', + launchTime: new Date(), + type: 'Org', + owner: ORG, + }, + { + instanceId: 'i-4-idle-older-than-minimum-time-running', + launchTime: moment(new Date()) + .subtract(MINIMUM_TIME_RUNNING + 3, 'minutes') + .toDate(), + type: 'Org', + owner: ORG, + }, +]; + +const githubRunnersRegistered = [ + { + id: 1, + name: 'i-1-idle', + os: 'linux', + status: 'online', + busy: false, + labels: [], + }, + { + id: 2, + name: 'i-2-busy', + os: 'linux', + status: 'online', + busy: true, + labels: [], + }, + { + id: 3, + name: 'i-3-offline', + os: 'linux', + status: 'offline', + busy: false, + labels: [], + }, + { + id: 3, + name: 'i-4-idle-older-than-minimum-time-running', + os: 'linux', + status: 'online', + busy: false, + labels: [], + }, +]; + +beforeEach(() => { + nock.disableNetConnect(); + jest.resetModules(); + jest.clearAllMocks(); + process.env = { ...cleanEnv }; + process.env.GITHUB_APP_KEY_BASE64 = 'TEST_CERTIFICATE_DATA'; + process.env.GITHUB_APP_ID = '1337'; + process.env.GITHUB_APP_CLIENT_ID = 'TEST_CLIENT_ID'; + process.env.GITHUB_APP_CLIENT_SECRET = 'TEST_CLIENT_SECRET'; + process.env.RUNNERS_MAXIMUM_COUNT = '3'; + process.env.ENVIRONMENT = 'unit-test-environment'; + process.env.ENABLE_ORGANIZATION_RUNNERS = 'true'; + process.env.LAUNCH_TEMPLATE_NAME = 'lt-1'; + process.env.SUBNET_IDS = 'subnet-123'; + process.env.SSM_TOKEN_PATH = '/github-action-runners/default/runners/tokens'; + process.env.INSTANCE_TYPES = 'm5.large'; + process.env.INSTANCE_TARGET_CAPACITY_TYPE = 'spot'; + process.env.RUNNER_OWNER = ORG; + process.env.RUNNER_BOOT_TIME_IN_MINUTES = MINIMUM_TIME_RUNNING.toString(); + + const mockTokenReturnValue = { + data: { + token: '1234abcd', + }, + }; + mockOctokit.actions.createRegistrationTokenForOrg.mockImplementation(() => mockTokenReturnValue); + + mockOctokit.paginate.mockImplementation(() => githubRunnersRegistered); + + mockListRunners.mockImplementation(async () => ec2InstancesRegistered); + + const mockInstallationIdReturnValueOrgs = { + data: { + id: 1, + }, + }; + mockOctokit.apps.getOrgInstallation.mockImplementation(() => mockInstallationIdReturnValueOrgs); + + mockedAppAuth.mockResolvedValue({ + type: 'app', + token: 'token', + appId: 1, + expiresAt: 'some-date', + }); + mockedInstallationAuth.mockResolvedValue({ + type: 'token', + tokenType: 'installation', + token: 'token', + createdAt: 'some-date', + expiresAt: 'some-date', + permissions: {}, + repositorySelection: 'all', + installationId: 0, + }); + + mockCreateClient.mockResolvedValue(new mocktokit()); +}); + +describe('Test simple pool.', () => { + describe('With GitHub Cloud', () => { + it('Top up pool with pool size 2 registered.', async () => { + await expect(await adjust({ poolSize: 3 })).resolves; + expect(createRunners).toHaveBeenCalledTimes(1); + expect(createRunners).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ numberOfRunners: 1 }), + expect.anything(), + ); + }); + + it('Should not top up if pool size is reached.', async () => { + await expect(await adjust({ poolSize: 1 })).resolves; + expect(createRunners).not.toHaveBeenCalled(); + }); + + it('Should top up if pool size is not reached including a booting instance.', async () => { + mockListRunners.mockImplementation(async () => [ + ...ec2InstancesRegistered, + { + instanceId: 'i-4-still-booting', + launchTime: moment(new Date()) + .subtract(MINIMUM_TIME_RUNNING - 3, 'minutes') + .toDate(), + type: 'Org', + owner: ORG, + }, + { + instanceId: 'i-5-orphan', + launchTime: moment(new Date()) + .subtract(MINIMUM_TIME_RUNNING + 3, 'minutes') + .toDate(), + type: 'Org', + owner: ORG, + }, + ]); + + // 2 idle + 1 booting = 3, top up with 2 to match a pool of 5 + await expect(await adjust({ poolSize: 5 })).resolves; + expect(createRunners).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ numberOfRunners: 2 }), + expect.anything(), + ); + }); + + it('Should not top up if pool size is reached including a booting instance.', async () => { + mockListRunners.mockImplementation(async () => [ + ...ec2InstancesRegistered, + { + instanceId: 'i-4-still-booting', + launchTime: moment(new Date()) + .subtract(MINIMUM_TIME_RUNNING - 3, 'minutes') + .toDate(), + type: 'Org', + owner: ORG, + }, + { + instanceId: 'i-5-orphan', + launchTime: moment(new Date()) + .subtract(MINIMUM_TIME_RUNNING + 3, 'minutes') + .toDate(), + type: 'Org', + owner: ORG, + }, + ]); + + await expect(await adjust({ poolSize: 2 })).resolves; + expect(createRunners).not.toHaveBeenCalled(); + }); + }); + + describe('With GHES', () => { + beforeEach(() => { + process.env.GHES_URL = 'https://github.enterprise.something'; + }); + + it('Top up if the pool size is set to 5', async () => { + await expect(await adjust({ poolSize: 5 })).resolves; + // 2 idle, top up with 3 to match a pool of 5 + expect(createRunners).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ numberOfRunners: 3 }), + expect.anything(), + ); + }); + }); + + describe('With Runner Name Prefix', () => { + beforeEach(() => { + process.env.RUNNER_NAME_PREFIX = 'runner-prefix_'; + }); + + it('Should top up with fewer runners when there are idle prefixed runners', async () => { + // Add prefixed runners to github + mockOctokit.paginate.mockImplementation(async () => [ + ...githubRunnersRegistered, + { + id: 5, + name: 'runner-prefix_i-5-idle', + os: 'linux', + status: 'online', + busy: false, + labels: [], + }, + { + id: 6, + name: 'runner-prefix_i-6-idle', + os: 'linux', + status: 'online', + busy: false, + labels: [], + }, + ]); + + // Add instances in ec2 + mockListRunners.mockImplementation(async () => [ + ...ec2InstancesRegistered, + { + instanceId: 'i-5-idle', + launchTime: new Date(), + type: 'Org', + owner: ORG, + }, + { + instanceId: 'i-6-idle', + launchTime: new Date(), + type: 'Org', + owner: ORG, + }, + ]); + + await expect(await adjust({ poolSize: 5 })).resolves; + // 2 idle, 2 prefixed idle top up with 1 to match a pool of 5 + expect(createRunners).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ numberOfRunners: 1 }), + expect.anything(), + ); + }); + }); +}); diff --git a/lambdas/functions/control-plane/src/pool/pool.ts b/lambdas/functions/control-plane/src/pool/pool.ts new file mode 100644 index 0000000000..736ac5ca47 --- /dev/null +++ b/lambdas/functions/control-plane/src/pool/pool.ts @@ -0,0 +1,161 @@ +import { Octokit } from '@octokit/rest'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import yn from 'yn'; + +import { bootTimeExceeded, listEC2Runners } from '../aws/runners'; +import { RunnerList } from '../aws/runners.d'; +import { createGithubAppAuth, createGithubInstallationAuth, createOctoClient } from '../gh-auth/gh-auth'; +import { createRunners } from '../scale-runners/scale-up'; + +const logger = createChildLogger('pool'); + +export interface PoolEvent { + poolSize: number; +} + +interface RunnerStatus { + busy: boolean; + status: string; +} + +export async function adjust(event: PoolEvent): Promise { + logger.info(`Checking current pool size against pool of size: ${event.poolSize}`); + const runnerLabels = process.env.RUNNER_LABELS || ''; + const runnerGroup = process.env.RUNNER_GROUP_NAME || ''; + const runnerNamePrefix = process.env.RUNNER_NAME_PREFIX || ''; + const environment = process.env.ENVIRONMENT; + const ghesBaseUrl = process.env.GHES_URL; + const ssmTokenPath = process.env.SSM_TOKEN_PATH; + const ssmConfigPath = process.env.SSM_CONFIG_PATH || ''; + const subnets = process.env.SUBNET_IDS.split(','); + const instanceTypes = process.env.INSTANCE_TYPES.split(','); + const instanceTargetCapacityType = process.env.INSTANCE_TARGET_CAPACITY_TYPE; + const ephemeral = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false }); + const enableJitConfig = yn(process.env.ENABLE_JIT_CONFIG, { default: ephemeral }); + const disableAutoUpdate = yn(process.env.DISABLE_RUNNER_AUTOUPDATE, { default: false }); + const launchTemplateName = process.env.LAUNCH_TEMPLATE_NAME; + const instanceMaxSpotPrice = process.env.INSTANCE_MAX_SPOT_PRICE; + const instanceAllocationStrategy = process.env.INSTANCE_ALLOCATION_STRATEGY || 'lowest-price'; // same as AWS default + const runnerOwner = process.env.RUNNER_OWNER; + const amiIdSsmParameterName = process.env.AMI_ID_SSM_PARAMETER_NAME; + const tracingEnabled = yn(process.env.POWERTOOLS_TRACE_ENABLED, { default: false }); + const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS + ? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string]) + : []; + + let ghesApiUrl = ''; + if (ghesBaseUrl) { + ghesApiUrl = `${ghesBaseUrl}/api/v3`; + } + + const installationId = await getInstallationId(ghesApiUrl, runnerOwner); + const ghAuth = await createGithubInstallationAuth(installationId, ghesApiUrl); + const githubInstallationClient = await createOctoClient(ghAuth.token, ghesApiUrl); + + // Get statusses of runners registed in GitHub + const runnerStatusses = await getGitHubRegisteredRunnnerStatusses( + githubInstallationClient, + runnerOwner, + runnerNamePrefix, + ); + + // Look up the managed ec2 runners in AWS, but running does not mean idle + const ec2runners = await listEC2Runners({ + environment, + runnerOwner, + runnerType: 'Org', + statuses: ['running'], + }); + + const numberOfRunnersInPool = calculatePooSize(ec2runners, runnerStatusses); + const topUp = event.poolSize - numberOfRunnersInPool; + + if (topUp > 0) { + logger.info(`The pool will be topped up with ${topUp} runners.`); + await createRunners( + { + ephemeral, + enableJitConfig, + ghesBaseUrl, + runnerLabels, + runnerGroup, + runnerOwner, + runnerNamePrefix, + runnerType: 'Org', + disableAutoUpdate: disableAutoUpdate, + ssmTokenPath, + ssmConfigPath, + }, + { + ec2instanceCriteria: { + instanceTypes, + targetCapacityType: instanceTargetCapacityType, + maxSpotPrice: instanceMaxSpotPrice, + instanceAllocationStrategy: instanceAllocationStrategy, + }, + environment, + launchTemplateName, + subnets, + numberOfRunners: topUp, + amiIdSsmParameterName, + tracingEnabled, + onDemandFailoverOnError, + }, + githubInstallationClient, + ); + } else { + logger.info(`Pool will not be topped up. Found ${numberOfRunnersInPool} managed idle runners.`); + } +} + +async function getInstallationId(ghesApiUrl: string, org: string): Promise { + const ghAuth = await createGithubAppAuth(undefined, ghesApiUrl); + const githubClient = await createOctoClient(ghAuth.token, ghesApiUrl); + + return ( + await githubClient.apps.getOrgInstallation({ + org, + }) + ).data.id; +} + +function calculatePooSize(ec2runners: RunnerList[], runnerStatus: Map): number { + // Runner should be considered idle if it is still booting, or is idle in GitHub + let numberOfRunnersInPool = 0; + for (const ec2Instance of ec2runners) { + if ( + runnerStatus.get(ec2Instance.instanceId)?.busy === false && + runnerStatus.get(ec2Instance.instanceId)?.status === 'online' + ) { + numberOfRunnersInPool++; + logger.debug(`Runner ${ec2Instance.instanceId} is idle in GitHub and counted as part of the pool`); + } else if (runnerStatus.get(ec2Instance.instanceId) != null) { + logger.debug(`Runner ${ec2Instance.instanceId} is not idle in GitHub and NOT counted as part of the pool`); + } else if (!bootTimeExceeded(ec2Instance)) { + numberOfRunnersInPool++; + logger.info(`Runner ${ec2Instance.instanceId} is still booting and counted as part of the pool`); + } else { + logger.debug( + `Runner ${ec2Instance.instanceId} is not idle in GitHub nor booting and not counted as part of the pool`, + ); + } + } + return numberOfRunnersInPool; +} + +async function getGitHubRegisteredRunnnerStatusses( + ghClient: Octokit, + runnerOwner: string, + runnerNamePrefix: string, +): Promise> { + const runners = await ghClient.paginate(ghClient.actions.listSelfHostedRunnersForOrg, { + org: runnerOwner, + per_page: 100, + }); + const runnerStatus = new Map(); + for (const runner of runners) { + runner.name = runnerNamePrefix ? runner.name.replace(runnerNamePrefix, '') : runner.name; + runnerStatus.set(runner.name, { busy: runner.busy, status: runner.status }); + } + return runnerStatus; +} diff --git a/modules/runners/lambdas/runners/src/scale-runners/ScaleError.ts b/lambdas/functions/control-plane/src/scale-runners/ScaleError.ts similarity index 100% rename from modules/runners/lambdas/runners/src/scale-runners/ScaleError.ts rename to lambdas/functions/control-plane/src/scale-runners/ScaleError.ts diff --git a/modules/runners/lambdas/runners/src/scale-runners/cache.ts b/lambdas/functions/control-plane/src/scale-runners/cache.ts similarity index 100% rename from modules/runners/lambdas/runners/src/scale-runners/cache.ts rename to lambdas/functions/control-plane/src/scale-runners/cache.ts diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-down-config.test.ts b/lambdas/functions/control-plane/src/scale-runners/scale-down-config.test.ts similarity index 51% rename from modules/runners/lambdas/runners/src/scale-runners/scale-down-config.test.ts rename to lambdas/functions/control-plane/src/scale-runners/scale-down-config.test.ts index 2bafce8b34..f3014e0b92 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-down-config.test.ts +++ b/lambdas/functions/control-plane/src/scale-runners/scale-down-config.test.ts @@ -1,16 +1,21 @@ import moment from 'moment-timezone'; -import { ScalingDownConfigList, getIdleRunnerCount } from './scale-down-config'; +import { EvictionStrategy, ScalingDownConfigList, getEvictionStrategy, getIdleRunnerCount } from './scale-down-config'; const DEFAULT_TIMEZONE = 'America/Los_Angeles'; const DEFAULT_IDLE_COUNT = 1; +const DEFAULT_EVICTION_STRATEGY: EvictionStrategy = 'oldest_first'; const now = moment.tz(new Date(), 'America/Los_Angeles'); -function getConfig(cronTabs: string[]): ScalingDownConfigList { +function getConfig( + cronTabs: string[], + evictionStrategy: EvictionStrategy | undefined = undefined, +): ScalingDownConfigList { return cronTabs.map((cron) => ({ cron: cron, idleCount: DEFAULT_IDLE_COUNT, timeZone: DEFAULT_TIMEZONE, + evictionStrategy, })); } @@ -31,4 +36,21 @@ describe('scaleDownConfig', () => { expect(getIdleRunnerCount(scaleDownConfig)).toEqual(DEFAULT_IDLE_COUNT); }); }); + + describe('Determine eviction strategy.', () => { + it('Default eviction strategy', async () => { + const scaleDownConfig = getConfig(['* * * * * *']); + expect(getEvictionStrategy(scaleDownConfig)).toEqual('oldest_first'); + }); + + it('Overriding eviction strategy to newest_first', async () => { + const scaleDownConfig = getConfig(['* * * * * *'], 'newest_first'); + expect(getEvictionStrategy(scaleDownConfig)).toEqual('newest_first'); + }); + + it('No active cron configuration', async () => { + const scaleDownConfig = getConfig(['* * * * * ' + ((now.day() + 1) % 7)]); + expect(getEvictionStrategy(scaleDownConfig)).toEqual(DEFAULT_EVICTION_STRATEGY); + }); + }); }); diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-down-config.ts b/lambdas/functions/control-plane/src/scale-runners/scale-down-config.ts similarity index 52% rename from modules/runners/lambdas/runners/src/scale-runners/scale-down-config.ts rename to lambdas/functions/control-plane/src/scale-runners/scale-down-config.ts index b853a24432..506cee81e0 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-down-config.ts +++ b/lambdas/functions/control-plane/src/scale-runners/scale-down-config.ts @@ -1,13 +1,18 @@ +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; import parser from 'cron-parser'; import moment from 'moment'; export type ScalingDownConfigList = ScalingDownConfig[]; +export type EvictionStrategy = 'newest_first' | 'oldest_first'; export interface ScalingDownConfig { cron: string; idleCount: number; timeZone: string; + evictionStrategy?: EvictionStrategy; } +const logger = createChildLogger('scale-down-config.ts'); + function inPeriod(period: ScalingDownConfig): boolean { const now = moment(new Date()); const expr = parser.parseExpression(period.cron, { @@ -25,3 +30,14 @@ export function getIdleRunnerCount(scalingDownConfigs: ScalingDownConfigList): n } return 0; } + +export function getEvictionStrategy(scalingDownConfigs: ScalingDownConfigList): EvictionStrategy { + for (const scalingDownConfig of scalingDownConfigs) { + if (inPeriod(scalingDownConfig)) { + const evictionStrategy = scalingDownConfig.evictionStrategy ?? 'oldest_first'; + logger.debug(`Using evictionStrategy '${evictionStrategy}' for period ${scalingDownConfig.cron}`); + return evictionStrategy; + } + } + return 'oldest_first'; +} diff --git a/lambdas/functions/control-plane/src/scale-runners/scale-down.test.ts b/lambdas/functions/control-plane/src/scale-runners/scale-down.test.ts new file mode 100644 index 0000000000..510d591adb --- /dev/null +++ b/lambdas/functions/control-plane/src/scale-runners/scale-down.test.ts @@ -0,0 +1,556 @@ +import { Octokit } from '@octokit/rest'; +import { mocked } from 'jest-mock'; +import moment from 'moment'; +import nock from 'nock'; + +import { RunnerInfo, RunnerList } from '../aws/runners.d'; +import * as ghAuth from '../gh-auth/gh-auth'; +import { listEC2Runners, terminateRunner } from './../aws/runners'; +import { githubCache } from './cache'; +import { newestFirstStrategy, oldestFirstStrategy, scaleDown } from './scale-down'; + +const mockOctokit = { + apps: { + getOrgInstallation: jest.fn(), + getRepoInstallation: jest.fn(), + }, + actions: { + listSelfHostedRunnersForRepo: jest.fn(), + listSelfHostedRunnersForOrg: jest.fn(), + deleteSelfHostedRunnerFromOrg: jest.fn(), + deleteSelfHostedRunnerFromRepo: jest.fn(), + getSelfHostedRunnerForOrg: jest.fn(), + getSelfHostedRunnerForRepo: jest.fn(), + }, + paginate: jest.fn(), +}; +jest.mock('@octokit/rest', () => ({ + Octokit: jest.fn().mockImplementation(() => mockOctokit), +})); + +jest.mock('./../aws/runners', () => ({ + ...jest.requireActual('./../aws/runners'), + tag: jest.fn(), + terminateRunner: jest.fn(), + listEC2Runners: jest.fn(), +})); +jest.mock('./../gh-auth/gh-auth'); +jest.mock('./cache'); + +const mocktokit = Octokit as jest.MockedClass; +const mockedAppAuth = mocked(ghAuth.createGithubAppAuth, { shallow: false }); +const mockedInstallationAuth = mocked(ghAuth.createGithubInstallationAuth, { shallow: false }); +const mockCreateClient = mocked(ghAuth.createOctoClient, { shallow: false }); +const mockListRunners = mocked(listEC2Runners); +const mockTerminateRunners = mocked(terminateRunner); + +export interface TestData { + repositoryName: string; + repositoryOwner: string; +} + +const cleanEnv = process.env; + +const ENVIRONMENT = 'unit-test-environment'; +const MINIMUM_TIME_RUNNING_IN_MINUTES = 30; +const MINIMUM_BOOT_TIME = 5; +const TEST_DATA: TestData = { + repositoryName: 'hello-world', + repositoryOwner: 'Codertocat', +}; + +interface RunnerTestItem extends RunnerList { + registered: boolean; + orphan: boolean; + shouldBeTerminated: boolean; +} + +describe('Scale down runners', () => { + beforeEach(() => { + process.env = { ...cleanEnv }; + process.env.GITHUB_APP_KEY_BASE64 = 'TEST_CERTIFICATE_DATA'; + process.env.GITHUB_APP_ID = '1337'; + process.env.GITHUB_APP_CLIENT_ID = 'TEST_CLIENT_ID'; + process.env.GITHUB_APP_CLIENT_SECRET = 'TEST_CLIENT_SECRET'; + process.env.RUNNERS_MAXIMUM_COUNT = '3'; + process.env.SCALE_DOWN_CONFIG = '[]'; + process.env.ENVIRONMENT = ENVIRONMENT; + process.env.MINIMUM_RUNNING_TIME_IN_MINUTES = MINIMUM_TIME_RUNNING_IN_MINUTES.toString(); + process.env.RUNNER_BOOT_TIME_IN_MINUTES = MINIMUM_BOOT_TIME.toString(); + + nock.disableNetConnect(); + jest.clearAllMocks(); + jest.resetModules(); + githubCache.clients.clear(); + githubCache.runners.clear(); + mockOctokit.apps.getOrgInstallation.mockImplementation(() => ({ + data: { + id: 'ORG', + }, + })); + mockOctokit.apps.getRepoInstallation.mockImplementation(() => ({ + data: { + id: 'REPO', + }, + })); + + mockOctokit.paginate.mockResolvedValue([]); + mockOctokit.actions.deleteSelfHostedRunnerFromRepo.mockImplementation((repo) => { + // check if repo.runner_id contains the word buys. If yest throw an error else return 204 + if (repo.runner_id.includes('busy')) { + throw Error(); + } else { + return { status: 204 }; + } + }); + + mockOctokit.actions.deleteSelfHostedRunnerFromOrg.mockImplementation((repo) => { + // check if repo.runner_id contains the word buys. If yest throw an error else return 204 + if (repo.runner_id.includes('busy')) { + throw Error(); + } else { + return { status: 204 }; + } + }); + + mockOctokit.actions.getSelfHostedRunnerForRepo.mockImplementation((repo) => { + if (repo.runner_id.includes('busy')) { + return { + data: { busy: true }, + }; + } else { + return { + data: { busy: false }, + }; + } + }); + mockOctokit.actions.getSelfHostedRunnerForOrg.mockImplementation((repo) => { + if (repo.runner_id.includes('busy')) { + return { + data: { busy: true }, + }; + } else { + return { + data: { busy: false }, + }; + } + }); + + mockTerminateRunners.mockImplementation(async () => { + return; + }); + mockedAppAuth.mockResolvedValue({ + type: 'app', + token: 'token', + appId: 1, + expiresAt: 'some-date', + }); + mockedInstallationAuth.mockResolvedValue({ + type: 'token', + tokenType: 'installation', + token: 'token', + createdAt: 'some-date', + expiresAt: 'some-date', + permissions: {}, + repositorySelection: 'all', + installationId: 0, + }); + mockCreateClient.mockResolvedValue(new mocktokit()); + }); + + const endpoints = ['https://api.github.com', 'https://github.enterprise.something']; + + describe.each(endpoints)('for %s', (endpoint) => { + beforeEach(() => { + if (endpoint.includes('enterprise')) { + process.env.GHES_URL = endpoint; + } + }); + + type RunnerType = 'Repo' | 'Org'; + const runnerTypes: RunnerType[] = ['Org', 'Repo']; + describe.each(runnerTypes)('For %s runners.', (type) => { + it('Should not call terminate when no runners online.', async () => { + // setup + mockListRunners.mockResolvedValue([]); + + // act + await scaleDown(); + + // assert + expect(listEC2Runners).toHaveBeenCalledWith({ + environment: ENVIRONMENT, + }); + expect(terminateRunner).not; + expect(mockOctokit.apps.getRepoInstallation).not; + expect(mockOctokit.apps.getRepoInstallation).not; + }); + + // run same test for the valutes type: 'Repo' and 'Org' + it(`Should terminate runner without idle config ${type} runners.`, async () => { + // setup + const runners = [ + createRunnerTestData('idle-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES - 1, true, false, false), + createRunnerTestData('idle-2', type, MINIMUM_TIME_RUNNING_IN_MINUTES + 4, true, false, true), + createRunnerTestData('busy-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES + 3, true, false, false), + createRunnerTestData('booting-1', type, MINIMUM_BOOT_TIME - 1, false, false, false), + ]; + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + // act + await scaleDown(); + + // assert + expect(listEC2Runners).toHaveBeenCalledWith({ + environment: ENVIRONMENT, + }); + + if (type === 'Repo') { + expect(mockOctokit.apps.getRepoInstallation).toHaveBeenCalled(); + } else { + expect(mockOctokit.apps.getOrgInstallation).toHaveBeenCalled(); + } + + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should respect idle runner with minimum running time not exceeded.`, async () => { + // setup + const runners = [createRunnerTestData('idle-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES - 1, true, false, false)]; + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + + // act + await scaleDown(); + + // assert + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should respect booting runner.`, async () => { + // setup + const runners = [createRunnerTestData('booting-1', type, MINIMUM_BOOT_TIME - 1, false, false, false)]; + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + + // act + await scaleDown(); + + // assert + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should respect busy runner.`, async () => { + // setup + const runners = [createRunnerTestData('busy-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES + 1, true, false, false)]; + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + + // act + await scaleDown(); + + // assert + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should not terminate a runner that became busy just before deregister runner.`, async () => { + // setup + const runners = [ + createRunnerTestData( + 'job-just-start-at-deregister-1', + type, + MINIMUM_TIME_RUNNING_IN_MINUTES + 1, + true, + false, + false, + ), + ]; + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + mockOctokit.actions.deleteSelfHostedRunnerFromRepo.mockImplementation((repo) => { + return { status: 500 }; + }); + + mockOctokit.actions.deleteSelfHostedRunnerFromOrg.mockImplementation((repo) => { + return { status: 500 }; + }); + + // act and ensure no exception is thrown + await expect(scaleDown()).resolves.not.toThrow(); + + // assert + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should terminate orphan.`, async () => { + // setup + const runners = [createRunnerTestData('orphan-1', type, MINIMUM_BOOT_TIME + 1, false, true, true)]; + + mockGitHubRunners([]); + mockListRunners.mockResolvedValue(runners); + + // act + await scaleDown(); + + // assert + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should orphan termination failure is not resulting in an exception..`, async () => { + // setup + const runners = [createRunnerTestData('orphan-1', type, MINIMUM_BOOT_TIME + 1, false, true, true)]; + + mockGitHubRunners([]); + mockListRunners.mockResolvedValue(runners); + mockTerminateRunners.mockRejectedValue(new Error('Termination failed')); + + // act and ensure no exception is thrown + await expect(scaleDown()).resolves.not.toThrow(); + }); + + it(`Should not terminate instance in case de-register fails.`, async () => { + // setup + const runners = [createRunnerTestData('idle-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES + 1, true, true, false)]; + + mockOctokit.actions.deleteSelfHostedRunnerFromOrg.mockImplementation(() => { + return { status: 500 }; + }); + mockOctokit.actions.deleteSelfHostedRunnerFromRepo.mockImplementation(() => { + return { status: 500 }; + }); + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + + // act and should resolve + await expect(scaleDown()).resolves.not.toThrow(); + + // assert + checkTerminated(runners); + checkNonTerminated(runners); + }); + + it(`Should not throw an exception in case of failure during removing a runner.`, async () => { + // setup + const runners = [createRunnerTestData('idle-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES + 1, true, true, false)]; + + mockOctokit.actions.deleteSelfHostedRunnerFromOrg.mockImplementation(() => { + throw new Error('Failed to delete runner'); + }); + mockOctokit.actions.deleteSelfHostedRunnerFromRepo.mockImplementation(() => { + throw new Error('Failed to delete runner'); + }); + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + + // act + await expect(scaleDown()).resolves.not.toThrow(); + }); + + const evictionStrategies = ['oldest_first', 'newest_first']; + describe.each(evictionStrategies)('When idle config defined', (evictionStrategy) => { + const defaultConfig = { + idleCount: 1, + cron: '* * * * * *', + timeZone: 'Europe/Amsterdam', + evictionStrategy, + }; + + beforeEach(() => { + process.env.SCALE_DOWN_CONFIG = JSON.stringify([defaultConfig]); + }); + + it(`Should terminate based on the the idle config with ${evictionStrategy} eviction strategy`, async () => { + // setup + const runnerToTerminateTime = + evictionStrategy === 'oldest_first' + ? MINIMUM_TIME_RUNNING_IN_MINUTES + 5 + : MINIMUM_TIME_RUNNING_IN_MINUTES + 1; + const runners = [ + createRunnerTestData('idle-1', type, MINIMUM_TIME_RUNNING_IN_MINUTES + 4, true, false, false), + createRunnerTestData('idle-to-terminate', type, runnerToTerminateTime, true, false, true), + ]; + + mockGitHubRunners(runners); + mockListRunners.mockResolvedValue(runners); + + // act + await scaleDown(); + + // assert + const runnersToTerminate = runners.filter((r) => r.shouldBeTerminated); + for (const toTerminate of runnersToTerminate) { + expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); + } + + const runnersNotToTerminate = runners.filter((r) => !r.shouldBeTerminated); + for (const notTerminated of runnersNotToTerminate) { + expect(terminateRunner).not.toHaveBeenCalledWith(notTerminated.instanceId); + } + }); + }); + }); + }); + + describe('When runners are sorted', () => { + const runners: RunnerInfo[] = [ + { + instanceId: '1', + launchTime: moment(new Date()).subtract(1, 'minute').toDate(), + owner: 'owner', + type: 'type', + }, + { + instanceId: '3', + launchTime: moment(new Date()).subtract(3, 'minute').toDate(), + owner: 'owner', + type: 'type', + }, + { + instanceId: '2', + launchTime: moment(new Date()).subtract(2, 'minute').toDate(), + owner: 'owner', + type: 'type', + }, + { + instanceId: '0', + launchTime: moment(new Date()).subtract(0, 'minute').toDate(), + owner: 'owner', + type: 'type', + }, + ]; + + it('Should sort runners descending for eviction strategy oldest first te keep the youngest.', () => { + runners.sort(oldestFirstStrategy); + expect(runners[0].instanceId).toEqual('0'); + expect(runners[1].instanceId).toEqual('1'); + expect(runners[2].instanceId).toEqual('2'); + expect(runners[3].instanceId).toEqual('3'); + }); + + it('Should sort runners ascending for eviction strategy newest first te keep oldest.', () => { + runners.sort(newestFirstStrategy); + expect(runners[0].instanceId).toEqual('3'); + expect(runners[1].instanceId).toEqual('2'); + expect(runners[2].instanceId).toEqual('1'); + expect(runners[3].instanceId).toEqual('0'); + }); + + it('Should sort runners with equal launch time.', () => { + const runnersTest = [...runners]; + const same = moment(new Date()).subtract(4, 'minute').toDate(); + runnersTest.push({ + instanceId: '4', + launchTime: same, + owner: 'owner', + type: 'type', + }); + runnersTest.push({ + instanceId: '5', + launchTime: same, + owner: 'owner', + type: 'type', + }); + runnersTest.sort(oldestFirstStrategy); + expect(runnersTest[3].launchTime).not.toEqual(same); + expect(runnersTest[4].launchTime).toEqual(same); + expect(runnersTest[5].launchTime).toEqual(same); + + runnersTest.sort(newestFirstStrategy); + expect(runnersTest[3].launchTime).not.toEqual(same); + expect(runnersTest[1].launchTime).toEqual(same); + expect(runnersTest[0].launchTime).toEqual(same); + }); + + it('Should sort runners even when launch time is undefined.', () => { + const runnersTest = [ + { + instanceId: '0', + launchTime: undefined, + owner: 'owner', + type: 'type', + }, + { + instanceId: '1', + launchTime: moment(new Date()).subtract(3, 'minute').toDate(), + owner: 'owner', + type: 'type', + }, + { + instanceId: '0', + launchTime: undefined, + owner: 'owner', + type: 'type', + }, + ]; + runnersTest.sort(oldestFirstStrategy); + expect(runnersTest[0].launchTime).toBeUndefined(); + expect(runnersTest[1].launchTime).toBeDefined(); + expect(runnersTest[2].launchTime).not.toBeDefined(); + }); + }); +}); + +function checkNonTerminated(runners: RunnerTestItem[]) { + const notTerminated = runners.filter((r) => !r.shouldBeTerminated); + for (const toTerminate of notTerminated) { + expect(terminateRunner).not.toHaveBeenCalledWith(toTerminate.instanceId); + } +} + +function checkTerminated(runners: RunnerTestItem[]) { + const runnersToTerminate = runners.filter((r) => r.shouldBeTerminated); + expect(terminateRunner).toHaveBeenCalledTimes(runnersToTerminate.length); + for (const toTerminate of runnersToTerminate) { + expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); + } +} + +function mockGitHubRunners(runners: RunnerTestItem[]) { + mockOctokit.paginate.mockResolvedValue( + runners + .filter((r) => r.registered) + .map((r) => { + return { + id: r.instanceId, + name: r.instanceId, + }; + }), + ); +} + +function createRunnerTestData( + name: string, + type: 'Org' | 'Repo', + minutesLaunchedAgo: number, + registered: boolean, + orphan: boolean, + shouldBeTerminated: boolean, + owner?: string, +): RunnerTestItem { + return { + instanceId: `i-${name}-${type.toLowerCase()}`, + launchTime: moment(new Date()).subtract(minutesLaunchedAgo, 'minutes').toDate(), + type, + owner: owner + ? owner + : type === 'Repo' + ? `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}` + : `${TEST_DATA.repositoryOwner}`, + registered, + orphan, + shouldBeTerminated, + }; +} diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-down.ts b/lambdas/functions/control-plane/src/scale-runners/scale-down.ts similarity index 64% rename from modules/runners/lambdas/runners/src/scale-runners/scale-down.ts rename to lambdas/functions/control-plane/src/scale-runners/scale-down.ts index 605221c58f..96b4dd4c76 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-down.ts +++ b/lambdas/functions/control-plane/src/scale-runners/scale-down.ts @@ -1,24 +1,25 @@ import { Octokit } from '@octokit/rest'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; import moment from 'moment'; import { createGithubAppAuth, createGithubInstallationAuth, createOctoClient } from '../gh-auth/gh-auth'; -import { LogFields, logger as rootLogger } from '../logger'; -import { RunnerInfo, RunnerList, listEC2Runners, terminateRunner } from './../aws/runners'; +import { bootTimeExceeded, listEC2Runners, terminateRunner } from './../aws/runners'; +import { RunnerInfo, RunnerList } from './../aws/runners.d'; import { GhRunners, githubCache } from './cache'; -import { ScalingDownConfig, getIdleRunnerCount } from './scale-down-config'; +import { ScalingDownConfig, getEvictionStrategy, getIdleRunnerCount } from './scale-down-config'; -const logger = rootLogger.getChildLogger({ name: 'scale-down' }); +const logger = createChildLogger('scale-down'); async function getOrCreateOctokit(runner: RunnerInfo): Promise { const key = runner.owner; const cachedOctokit = githubCache.clients.get(key); if (cachedOctokit) { - logger.debug(`[createGitHubClientForRunner] Cache hit for ${key}`, LogFields.print()); + logger.debug(`[createGitHubClientForRunner] Cache hit for ${key}`); return cachedOctokit; } - logger.debug(`[createGitHubClientForRunner] Cache miss for ${key}`, LogFields.print()); + logger.debug(`[createGitHubClientForRunner] Cache miss for ${key}`); const ghesBaseUrl = process.env.GHES_URL; let ghesApiUrl = ''; if (ghesBaseUrl) { @@ -60,10 +61,7 @@ async function getGitHubRunnerBusyState(client: Octokit, ec2runner: RunnerInfo, repo: ec2runner.owner.split('/')[1], }); - logger.info( - `Runner '${ec2runner.instanceId}' - GitHub Runner ID '${runnerId}' - Busy: ${state.data.busy}`, - LogFields.print(), - ); + logger.info(`Runner '${ec2runner.instanceId}' - GitHub Runner ID '${runnerId}' - Busy: ${state.data.busy}`); return state.data.busy; } @@ -72,11 +70,11 @@ async function listGitHubRunners(runner: RunnerInfo): Promise { const key = runner.owner as string; const cachedRunners = githubCache.runners.get(key); if (cachedRunners) { - logger.debug(`[listGithubRunners] Cache hit for ${key}`, LogFields.print()); + logger.debug(`[listGithubRunners] Cache hit for ${key}`); return cachedRunners; } - logger.debug(`[listGithubRunners] Cache miss for ${key}`, LogFields.print()); + logger.debug(`[listGithubRunners] Cache miss for ${key}`); const client = await getOrCreateOctokit(runner); const runners = runner.type === 'Org' @@ -90,7 +88,8 @@ async function listGitHubRunners(runner: RunnerInfo): Promise { per_page: 100, }); githubCache.runners.set(key, runners); - + logger.debug(`[listGithubRunners] Cache set for ${key}`); + logger.debug(`[listGithubRunners] Runners: ${JSON.stringify(runners)}`); return runners; } @@ -101,12 +100,6 @@ function runnerMinimumTimeExceeded(runner: RunnerInfo): boolean { return launchTimePlusMinimum < now; } -function bootTimeExceeded(ec2Runner: RunnerInfo): boolean { - const runnerBootTimeInMinutes = process.env.RUNNER_BOOT_TIME_IN_MINUTES; - const launchTimePlusBootTime = moment(ec2Runner.launchTime).utc().add(runnerBootTimeInMinutes, 'minutes'); - return launchTimePlusBootTime < moment(new Date()).utc(); -} - async function removeRunner(ec2runner: RunnerInfo, ghRunnerIds: number[]): Promise { const githubAppClient = await getOrCreateOctokit(ec2runner); try { @@ -137,21 +130,17 @@ async function removeRunner(ec2runner: RunnerInfo, ghRunnerIds: number[]): Promi if (statuses.every((status) => status == 204)) { await terminateRunner(ec2runner.instanceId); - logger.info( - `AWS runner instance '${ec2runner.instanceId}' is terminated and GitHub runner is de-registered.`, - LogFields.print(), - ); + logger.info(`AWS runner instance '${ec2runner.instanceId}' is terminated and GitHub runner is de-registered.`); } else { - logger.error(`Failed to de-register GitHub runner: ${statuses}`, LogFields.print()); + logger.error(`Failed to de-register GitHub runner: ${statuses}`); } } else { - logger.info( - `Runner '${ec2runner.instanceId}' cannot be de-registered, because it is still busy.`, - LogFields.print(), - ); + logger.info(`Runner '${ec2runner.instanceId}' cannot be de-registered, because it is still busy.`); } } catch (e) { - logger.error(`Runner '${ec2runner.instanceId}' cannot be de-registered. Error: ${e}`, LogFields.print()); + logger.error(`Runner '${ec2runner.instanceId}' cannot be de-registered. Error: ${e}`, { + error: e as Error, + }); } } @@ -160,26 +149,33 @@ async function evaluateAndRemoveRunners( scaleDownConfigs: ScalingDownConfig[], ): Promise { let idleCounter = getIdleRunnerCount(scaleDownConfigs); + const evictionStrategy = getEvictionStrategy(scaleDownConfigs); const ownerTags = new Set(ec2Runners.map((runner) => runner.owner)); for (const ownerTag of ownerTags) { - const ec2RunnersFiltered = ec2Runners.filter((runner) => runner.owner === ownerTag); - logger.debug( - `Found: '${ec2RunnersFiltered.length}' active GitHub runners with owner tag: '${ownerTag}'`, - LogFields.print(), - ); + const ec2RunnersFiltered = ec2Runners + .filter((runner) => runner.owner === ownerTag) + .sort(evictionStrategy === 'oldest_first' ? oldestFirstStrategy : newestFirstStrategy); + logger.debug(`Found: '${ec2RunnersFiltered.length}' active GitHub runners with owner tag: '${ownerTag}'`); + logger.debug(`Active GitHub runners with owner tag: '${ownerTag}': ${JSON.stringify(ec2RunnersFiltered)}`); for (const ec2Runner of ec2RunnersFiltered) { const ghRunners = await listGitHubRunners(ec2Runner); const ghRunnersFiltered = ghRunners.filter((runner: { name: string }) => - runner.name.startsWith(ec2Runner.instanceId), + runner.name.endsWith(ec2Runner.instanceId), + ); + logger.debug( + `Found: '${ghRunnersFiltered.length}' GitHub runners for AWS runner instance: '${ec2Runner.instanceId}'`, + ); + logger.debug( + `GitHub runners for AWS runner instance: '${ec2Runner.instanceId}': ${JSON.stringify(ghRunnersFiltered)}`, ); if (ghRunnersFiltered.length) { if (runnerMinimumTimeExceeded(ec2Runner)) { if (idleCounter > 0) { idleCounter--; - logger.info(`Runner '${ec2Runner.instanceId}' will be kept idle.`, LogFields.print()); + logger.info(`Runner '${ec2Runner.instanceId}' will be kept idle.`); } else { - logger.info(`Runner '${ec2Runner.instanceId}' will be terminated.`, LogFields.print()); + logger.info(`Will try to terminate runners that are not busy`); await removeRunner( ec2Runner, ghRunnersFiltered.map((runner: { id: number }) => runner.id), @@ -188,10 +184,10 @@ async function evaluateAndRemoveRunners( } } else { if (bootTimeExceeded(ec2Runner)) { - logger.info(`Runner '${ec2Runner.instanceId}' is orphaned and will be removed.`, LogFields.print()); + logger.info(`Runner '${ec2Runner.instanceId}' is orphaned and will be removed.`); terminateOrphan(ec2Runner.instanceId); } else { - logger.debug(`Runner ${ec2Runner.instanceId} has not yet booted.`, LogFields.print()); + logger.debug(`Runner ${ec2Runner.instanceId} has not yet booted.`); } } } @@ -202,37 +198,26 @@ async function terminateOrphan(instanceId: string): Promise { try { await terminateRunner(instanceId); } catch (e) { - logger.debug(`Orphan runner '${instanceId}' cannot be removed.`, LogFields.print()); + logger.debug(`Orphan runner '${instanceId}' cannot be removed.`); } } -async function listAndSortRunners(environment: string) { - return ( - await listEC2Runners({ - environment, - }) - ).sort((a, b): number => { - if (a.launchTime === undefined) return 1; - if (b.launchTime === undefined) return 1; - if (a.launchTime < b.launchTime) return 1; - if (a.launchTime > b.launchTime) return -1; - return 0; - }); +export function oldestFirstStrategy(a: RunnerInfo, b: RunnerInfo): number { + if (a.launchTime === undefined) return 1; + if (b.launchTime === undefined) return 1; + if (a.launchTime < b.launchTime) return 1; + if (a.launchTime > b.launchTime) return -1; + return 0; +} + +export function newestFirstStrategy(a: RunnerInfo, b: RunnerInfo): number { + return oldestFirstStrategy(a, b) * -1; } -/** - * We are moving to a new strategy to find and remove runners, this function will ensure - * during migration runners tagged in the old way are removed. - */ -function filterLegacyRunners(ec2runners: RunnerList[]): RunnerInfo[] { - return ec2runners - .filter((ec2Runner) => ec2Runner.repo || ec2Runner.org) - .map((ec2Runner) => ({ - instanceId: ec2Runner.instanceId, - launchTime: ec2Runner.launchTime, - type: ec2Runner.org ? 'Org' : 'Repo', - owner: ec2Runner.org ? (ec2Runner.org as string) : (ec2Runner.repo as string), - })); +async function listRunners(environment: string) { + return await listEC2Runners({ + environment, + }); } function filterRunners(ec2runners: RunnerList[]): RunnerInfo[] { @@ -244,28 +229,19 @@ export async function scaleDown(): Promise { const scaleDownConfigs = JSON.parse(process.env.SCALE_DOWN_CONFIG) as [ScalingDownConfig]; const environment = process.env.ENVIRONMENT; - // list and sort runners, newest first. This ensure we keep the newest runners longer. - const ec2Runners = await listAndSortRunners(environment); + const ec2Runners = await listRunners(environment); const activeEc2RunnersCount = ec2Runners.length; - logger.info( - `Found: '${activeEc2RunnersCount}' active GitHub EC2 runner instances before clean-up.`, - LogFields.print(), - ); + logger.info(`Found: '${activeEc2RunnersCount}' active GitHub EC2 runner instances before clean-up.`); + logger.debug(`Active GitHub EC2 runner instances: ${JSON.stringify(ec2Runners)}`); if (activeEc2RunnersCount === 0) { - logger.debug(`No active runners found for environment: '${environment}'`, LogFields.print()); + logger.debug(`No active runners found for environment: '${environment}'`); return; } - const legacyRunners = filterLegacyRunners(ec2Runners); - logger.debug(JSON.stringify(legacyRunners), LogFields.print()); - const runners = filterRunners(ec2Runners); + const runners = filterRunners(ec2Runners); await evaluateAndRemoveRunners(runners, scaleDownConfigs); - await evaluateAndRemoveRunners(legacyRunners, scaleDownConfigs); - const activeEc2RunnersCountAfter = (await listAndSortRunners(environment)).length; - logger.info( - `Found: '${activeEc2RunnersCountAfter}' active GitHub EC2 runners instances after clean-up.`, - LogFields.print(), - ); + const activeEc2RunnersCountAfter = (await listRunners(environment)).length; + logger.info(`Found: '${activeEc2RunnersCountAfter}' active GitHub EC2 runners instances after clean-up.`); } diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-up.test.ts b/lambdas/functions/control-plane/src/scale-runners/scale-up.test.ts similarity index 66% rename from modules/runners/lambdas/runners/src/scale-runners/scale-up.test.ts rename to lambdas/functions/control-plane/src/scale-runners/scale-up.test.ts index c325ff92fb..f14319a3b6 100644 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-up.test.ts +++ b/lambdas/functions/control-plane/src/scale-runners/scale-up.test.ts @@ -1,24 +1,35 @@ +import { GetParameterCommand, PutParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; import { Octokit } from '@octokit/rest'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; import { mocked } from 'jest-mock'; import nock from 'nock'; +import { performance } from 'perf_hooks'; import * as ghAuth from '../gh-auth/gh-auth'; -import { RunnerInputParameters, createRunner, listEC2Runners } from './../aws/runners'; +import { createRunner, listEC2Runners } from './../aws/runners'; +import { RunnerInputParameters } from './../aws/runners.d'; import ScaleError from './ScaleError'; import * as scaleUpModule from './scale-up'; const mockOctokit = { + paginate: jest.fn(), checks: { get: jest.fn() }, actions: { createRegistrationTokenForOrg: jest.fn(), createRegistrationTokenForRepo: jest.fn(), getJobForWorkflowRun: jest.fn(), + generateRunnerJitconfigForOrg: jest.fn(), + generateRunnerJitconfigForRepo: jest.fn(), }, apps: { getOrgInstallation: jest.fn(), getRepoInstallation: jest.fn(), }, }; +const mockCreateRunner = mocked(createRunner); +const mockListRunners = mocked(listEC2Runners); +const mockSSMClient = mockClient(SSMClient); jest.mock('@octokit/rest', () => ({ Octokit: jest.fn().mockImplementation(() => mockOctokit), @@ -26,6 +37,10 @@ jest.mock('@octokit/rest', () => ({ jest.mock('./../aws/runners'); jest.mock('./../gh-auth/gh-auth'); +export type RunnerType = 'ephemeral' | 'non-ephemeral'; + +// for ephemeral and non-ephemeral runners +const RUNNER_TYPES: RunnerType[] = ['ephemeral', 'non-ephemeral']; const mocktokit = Octokit as jest.MockedClass; const mockedAppAuth = mocked(ghAuth.createGithubAppAuth, { shallow: false }); @@ -53,9 +68,9 @@ const cleanEnv = process.env; const EXPECTED_RUNNER_PARAMS: RunnerInputParameters = { environment: 'unit-test-environment', - runnerServiceConfig: [`--url https://github.enterprise.something/${TEST_DATA.repositoryOwner}`, '--token 1234abcd'], runnerType: 'Org', runnerOwner: TEST_DATA.repositoryOwner, + numberOfRunners: 1, launchTemplateName: 'lt-1', ec2instanceCriteria: { instanceTypes: ['m5.large'], @@ -63,31 +78,53 @@ const EXPECTED_RUNNER_PARAMS: RunnerInputParameters = { instanceAllocationStrategy: 'lowest-price', }, subnets: ['subnet-123'], + tracingEnabled: false, + onDemandFailoverOnError: [], }; let expectedRunnerParams: RunnerInputParameters; -beforeEach(() => { - nock.disableNetConnect(); - jest.resetModules(); - jest.clearAllMocks(); +function setDefaults() { process.env = { ...cleanEnv }; process.env.GITHUB_APP_KEY_BASE64 = 'TEST_CERTIFICATE_DATA'; process.env.GITHUB_APP_ID = '1337'; process.env.GITHUB_APP_CLIENT_ID = 'TEST_CLIENT_ID'; process.env.GITHUB_APP_CLIENT_SECRET = 'TEST_CLIENT_SECRET'; process.env.RUNNERS_MAXIMUM_COUNT = '3'; - process.env.ENVIRONMENT = 'unit-test-environment'; + process.env.ENVIRONMENT = EXPECTED_RUNNER_PARAMS.environment; process.env.LAUNCH_TEMPLATE_NAME = 'lt-1'; process.env.SUBNET_IDS = 'subnet-123'; process.env.INSTANCE_TYPES = 'm5.large'; process.env.INSTANCE_TARGET_CAPACITY_TYPE = 'spot'; + process.env.ENABLE_ON_DEMAND_FAILOVER = undefined; +} + +beforeEach(() => { + nock.disableNetConnect(); + jest.resetModules(); + jest.clearAllMocks(); + setDefaults(); mockOctokit.actions.getJobForWorkflowRun.mockImplementation(() => ({ data: { status: 'queued', }, })); - + mockOctokit.paginate.mockImplementation(() => [ + { + id: 1, + name: 'Default', + }, + ]); + mockOctokit.actions.generateRunnerJitconfigForOrg.mockImplementation(() => ({ + data: { + encoded_jit_config: 'TEST_JIT_CONFIG_ORG', + }, + })); + mockOctokit.actions.generateRunnerJitconfigForRepo.mockImplementation(() => ({ + data: { + encoded_jit_config: 'TEST_JIT_CONFIG_REPO', + }, + })); mockOctokit.checks.get.mockImplementation(() => ({ data: { status: 'queued', @@ -113,7 +150,9 @@ beforeEach(() => { mockOctokit.actions.createRegistrationTokenForRepo.mockImplementation(() => mockTokenReturnValue); mockOctokit.apps.getOrgInstallation.mockImplementation(() => mockInstallationIdReturnValueOrgs); mockOctokit.apps.getRepoInstallation.mockImplementation(() => mockInstallationIdReturnValueRepos); - const mockListRunners = mocked(listEC2Runners); + mockCreateRunner.mockImplementation(async () => { + return ['i-12345']; + }); mockListRunners.mockImplementation(async () => [ { instanceId: 'i-1234', @@ -173,7 +212,16 @@ describe('scaleUp with GHES', () => { describe('on org level', () => { beforeEach(() => { process.env.ENABLE_ORGANIZATION_RUNNERS = 'true'; + process.env.ENABLE_EPHEMERAL_RUNNERS = 'true'; + process.env.RUNNER_NAME_PREFIX = 'unit-test-'; + process.env.RUNNER_GROUP_NAME = 'Default'; + process.env.SSM_CONFIG_PATH = '/github-action-runners/default/runners/config'; + process.env.SSM_TOKEN_PATH = '/github-action-runners/default/runners/config'; + process.env.RUNNER_LABELS = 'label1,label2'; + expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS }; + mockSSMClient.reset(); + mockSSMClient.on(GetParameterCommand).resolves({ Parameter: { Value: '1' } }); }); it('gets the current org level runners', async () => { @@ -187,12 +235,22 @@ describe('scaleUp with GHES', () => { it('does not create a token when maximum runners has been reached', async () => { process.env.RUNNERS_MAXIMUM_COUNT = '1'; + process.env.ENABLE_EPHEMERAL_RUNNERS = 'false'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); expect(mockOctokit.actions.createRegistrationTokenForOrg).not.toBeCalled(); expect(mockOctokit.actions.createRegistrationTokenForRepo).not.toBeCalled(); }); + it('does create a runner if maximum is set to -1', async () => { + process.env.RUNNERS_MAXIMUM_COUNT = '-1'; + process.env.ENABLE_EPHEMERAL_RUNNERS = 'false'; + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(listEC2Runners).not.toHaveBeenCalled(); + expect(createRunner).toHaveBeenCalled(); + }); + it('creates a token when maximum runners has not been reached', async () => { + process.env.ENABLE_EPHEMERAL_RUNNERS = 'false'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); expect(mockOctokit.actions.createRegistrationTokenForOrg).toBeCalledWith({ org: TEST_DATA.repositoryOwner, @@ -227,20 +285,10 @@ describe('scaleUp with GHES', () => { expect(createRunner).toBeCalledWith(expectedRunnerParams); }); - it('creates a runner with legacy event check_run', async () => { - await scaleUpModule.scaleUp('aws:sqs', { ...TEST_DATA, eventType: 'check_run' }); - expect(createRunner).toBeCalledWith(expectedRunnerParams); - }); - it('creates a runner with labels in a specific group', async () => { - process.env.RUNNER_EXTRA_LABELS = 'label1,label2'; + process.env.RUNNER_LABELS = 'label1,label2'; process.env.RUNNER_GROUP_NAME = 'TEST_GROUP'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [ - ...expectedRunnerParams.runnerServiceConfig, - '--labels label1,label2', - '--runnergroup TEST_GROUP', - ]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); @@ -249,18 +297,149 @@ describe('scaleUp with GHES', () => { await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); expect(createRunner).toBeCalledWith({ ...expectedRunnerParams, amiIdSsmParameterName: 'my-ami-id-param' }); }); - }); + it('Throws an error if runner group doesnt exist for ephemeral runners', async () => { + process.env.RUNNER_GROUP_NAME = 'test-runner-group'; + mockSSMClient.on(GetParameterCommand).rejects(); + await expect(scaleUpModule.scaleUp('aws:sqs', TEST_DATA)).rejects.toBeInstanceOf(Error); + expect(mockOctokit.paginate).toHaveBeenCalledTimes(1); + }); + + it('create SSM parameter for runner group id if it doesnt exist', async () => { + mockSSMClient.on(GetParameterCommand).rejects(); + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(mockOctokit.paginate).toHaveBeenCalledTimes(1); + expect(mockSSMClient).toHaveReceivedCommandTimes(PutParameterCommand, 2); + expect(mockSSMClient).toHaveReceivedNthSpecificCommandWith(1, PutParameterCommand, { + Name: `${process.env.SSM_CONFIG_PATH}/runner-group/${process.env.RUNNER_GROUP_NAME}`, + Value: '1', + Type: 'String', + }); + }); + + it('Doesnt create SSM parameter for runner group id if it exists', async () => { + mockSSMClient.on(GetParameterCommand).resolves({ Parameter: { Value: '1' } }); + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(mockOctokit.paginate).toHaveBeenCalledTimes(0); + expect(mockSSMClient).toHaveReceivedCommandTimes(PutParameterCommand, 1); + }); + + it('create start runner config for ephemeral runners ', async () => { + process.env.RUNNERS_MAXIMUM_COUNT = '2'; + mockSSMClient.on(GetParameterCommand).resolves({ Parameter: { Value: '1' } }); + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(mockOctokit.actions.generateRunnerJitconfigForOrg).toBeCalledWith({ + org: TEST_DATA.repositoryOwner, + name: 'unit-test-i-12345', + runner_group_id: 1, + labels: ['label1', 'label2'], + }); + expect(mockSSMClient).toHaveReceivedNthSpecificCommandWith(1, PutParameterCommand, { + Name: '/github-action-runners/default/runners/config/i-12345', + Value: 'TEST_JIT_CONFIG_ORG', + Type: 'SecureString', + Tags: [ + { + Key: 'InstanceId', + Value: 'i-12345', + }, + ], + }); + }); + + it('create start runner config for non-ephemeral runners ', async () => { + process.env.ENABLE_EPHEMERAL_RUNNERS = 'false'; + process.env.RUNNERS_MAXIMUM_COUNT = '2'; + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(mockOctokit.actions.generateRunnerJitconfigForOrg).not.toBeCalled(); + expect(mockOctokit.actions.createRegistrationTokenForOrg).toBeCalled(); + expect(mockSSMClient).toHaveReceivedNthSpecificCommandWith(1, PutParameterCommand, { + Name: '/github-action-runners/default/runners/config/i-12345', + Value: + '--url https://github.enterprise.something/Codertocat --token 1234abcd ' + + '--labels label1,label2 --runnergroup Default', + Type: 'SecureString', + Tags: [ + { + Key: 'InstanceId', + Value: 'i-12345', + }, + ], + }); + }); + it.each(RUNNER_TYPES)( + 'calls create start runner config of 40' + ' instances (ssm rate limit condition) to test time delay ', + async (type: RunnerType) => { + process.env.ENABLE_EPHEMERAL_RUNNERS = type === 'ephemeral' ? 'true' : 'false'; + process.env.RUNNERS_MAXIMUM_COUNT = '40'; + mockCreateRunner.mockImplementation(async () => { + return instances; + }); + mockListRunners.mockImplementation(async () => { + return []; + }); + mockSSMClient.on(GetParameterCommand).resolves({ Parameter: { Value: '1' } }); + const startTime = performance.now(); + const instances = [ + 'i-1234', + 'i-5678', + 'i-5567', + 'i-5569', + 'i-5561', + 'i-5560', + 'i-5566', + 'i-5536', + 'i-5526', + 'i-5516', + 'i-122', + 'i-123', + 'i-124', + 'i-125', + 'i-126', + 'i-127', + 'i-128', + 'i-129', + 'i-130', + 'i-131', + 'i-132', + 'i-133', + 'i-134', + 'i-135', + 'i-136', + 'i-137', + 'i-138', + 'i-139', + 'i-140', + 'i-141', + 'i-142', + 'i-143', + 'i-144', + 'i-145', + 'i-146', + 'i-147', + 'i-148', + 'i-149', + 'i-150', + 'i-151', + ]; + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + const endTime = performance.now(); + expect(endTime - startTime).toBeGreaterThan(1000); + expect(mockSSMClient).toHaveReceivedCommandTimes(PutParameterCommand, 40); + }, + 10000, + ); + }); describe('on repo level', () => { beforeEach(() => { process.env.ENABLE_ORGANIZATION_RUNNERS = 'false'; + process.env.RUNNER_NAME_PREFIX = 'unit-test'; expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS }; expectedRunnerParams.runnerType = 'Repo'; expectedRunnerParams.runnerOwner = `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`; - expectedRunnerParams.runnerServiceConfig = [ - `--url https://github.enterprise.something/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, - `--token 1234abcd`, - ]; + // `--url https://github.enterprise.something/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, + // `--token 1234abcd`, + // ]; }); it('gets the current repo level runners', async () => { @@ -280,6 +459,7 @@ describe('scaleUp with GHES', () => { }); it('creates a token when maximum runners has not been reached', async () => { + process.env.ENABLE_EPHEMERAL_RUNNERS = 'false'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); expect(mockOctokit.actions.createRegistrationTokenForOrg).not.toBeCalled(); expect(mockOctokit.actions.createRegistrationTokenForRepo).toBeCalledWith({ @@ -324,23 +504,15 @@ describe('scaleUp with GHES', () => { }); it('creates a runner with correct config and labels', async () => { - process.env.RUNNER_EXTRA_LABELS = 'label1,label2'; + process.env.RUNNER_LABELS = 'label1,label2'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [ - ...expectedRunnerParams.runnerServiceConfig, - `--labels label1,label2`, - ]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); it('creates a runner and ensure the group argument is ignored', async () => { - process.env.RUNNER_EXTRA_LABELS = 'label1,label2'; + process.env.RUNNER_LABELS = 'label1,label2'; process.env.RUNNER_GROUP_NAME = 'TEST_GROUP_IGNORED'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [ - ...expectedRunnerParams.runnerServiceConfig, - `--labels label1,label2`, - ]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); @@ -402,22 +574,11 @@ describe('scaleUp with public GH', () => { expect(listEC2Runners).not.toBeCalled(); }); - it('does not list runners when no workflows are queued (check_run)', async () => { - mockOctokit.checks.get.mockImplementation(() => ({ - data: { status: 'completed' }, - })); - await scaleUpModule.scaleUp('aws:sqs', { ...TEST_DATA, eventType: 'check_run' }); - expect(listEC2Runners).not.toBeCalled(); - }); - describe('on org level', () => { beforeEach(() => { process.env.ENABLE_ORGANIZATION_RUNNERS = 'true'; + process.env.RUNNER_NAME_PREFIX = 'unit-test'; expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS }; - expectedRunnerParams.runnerServiceConfig = [ - `--url https://github.com/${TEST_DATA.repositoryOwner}`, - `--token 1234abcd`, - ]; }); it('gets the current org level runners', async () => { @@ -449,34 +610,23 @@ describe('scaleUp with public GH', () => { expect(createRunner).toBeCalledWith(expectedRunnerParams); }); - it('creates a runner with legacy event check_run', async () => { - await scaleUpModule.scaleUp('aws:sqs', { ...TEST_DATA, eventType: 'check_run' }); - expect(createRunner).toBeCalledWith(expectedRunnerParams); - }); - it('creates a runner with labels in s specific group', async () => { - process.env.RUNNER_EXTRA_LABELS = 'label1,label2'; + process.env.RUNNER_LABELS = 'label1,label2'; process.env.RUNNER_GROUP_NAME = 'TEST_GROUP'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [ - ...expectedRunnerParams.runnerServiceConfig, - `--labels label1,label2`, - `--runnergroup TEST_GROUP`, - ]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); }); describe('on repo level', () => { beforeEach(() => { + mockSSMClient.reset(); + process.env.ENABLE_ORGANIZATION_RUNNERS = 'false'; + process.env.RUNNER_NAME_PREFIX = 'unit-test'; expectedRunnerParams = { ...EXPECTED_RUNNER_PARAMS }; expectedRunnerParams.runnerType = 'Repo'; expectedRunnerParams.runnerOwner = `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`; - expectedRunnerParams.runnerServiceConfig = [ - `--url https://github.com/${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, - `--token 1234abcd`, - ]; }); it('gets the current repo level runners', async () => { @@ -525,23 +675,25 @@ describe('scaleUp with public GH', () => { }); it('creates a runner with correct config and labels', async () => { - process.env.RUNNER_EXTRA_LABELS = 'label1,label2'; + process.env.RUNNER_LABELS = 'label1,label2'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [ - ...expectedRunnerParams.runnerServiceConfig, - `--labels label1,label2`, - ]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); + it('creates a runner with correct config and labels and on demand failover enabled.', async () => { + process.env.RUNNER_LABELS = 'label1,label2'; + process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS = JSON.stringify(['InsufficientInstanceCapacity']); + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(createRunner).toBeCalledWith({ + ...expectedRunnerParams, + onDemandFailoverOnError: ['InsufficientInstanceCapacity'], + }); + }); + it('creates a runner and ensure the group argument is ignored', async () => { - process.env.RUNNER_EXTRA_LABELS = 'label1,label2'; + process.env.RUNNER_LABELS = 'label1,label2'; process.env.RUNNER_GROUP_NAME = 'TEST_GROUP_IGNORED'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [ - ...expectedRunnerParams.runnerServiceConfig, - `--labels label1,label2`, - ]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); @@ -556,13 +708,70 @@ describe('scaleUp with public GH', () => { ).rejects.toBeInstanceOf(Error); }); - it('creates a ephemeral runner.', async () => { + it('creates a ephemeral runner with JIT config.', async () => { + process.env.ENABLE_EPHEMERAL_RUNNERS = 'true'; + process.env.ENABLE_JOB_QUEUED_CHECK = 'false'; + process.env.SSM_TOKEN_PATH = '/github-action-runners/default/runners/config'; + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(mockOctokit.actions.getJobForWorkflowRun).not.toBeCalled(); + expect(createRunner).toBeCalledWith(expectedRunnerParams); + + expect(mockSSMClient).toHaveReceivedNthSpecificCommandWith(1, PutParameterCommand, { + Name: '/github-action-runners/default/runners/config/i-12345', + Value: 'TEST_JIT_CONFIG_REPO', + Type: 'SecureString', + Tags: [ + { + Key: 'InstanceId', + Value: 'i-12345', + }, + ], + }); + }); + + it('creates a ephemeral runner with registration token.', async () => { process.env.ENABLE_EPHEMERAL_RUNNERS = 'true'; + process.env.ENABLE_JIT_CONFIG = 'false'; process.env.ENABLE_JOB_QUEUED_CHECK = 'false'; + process.env.SSM_TOKEN_PATH = '/github-action-runners/default/runners/config'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [...expectedRunnerParams.runnerServiceConfig, `--ephemeral`]; expect(mockOctokit.actions.getJobForWorkflowRun).not.toBeCalled(); expect(createRunner).toBeCalledWith(expectedRunnerParams); + + expect(mockSSMClient).toHaveReceivedNthSpecificCommandWith(1, PutParameterCommand, { + Name: '/github-action-runners/default/runners/config/i-12345', + Value: '--url https://github.com/Codertocat/hello-world --token 1234abcd --ephemeral', + Type: 'SecureString', + Tags: [ + { + Key: 'InstanceId', + Value: 'i-12345', + }, + ], + }); + }); + + it('JIT config is ingored for non-ephemeral runners.', async () => { + process.env.ENABLE_EPHEMERAL_RUNNERS = 'false'; + process.env.ENABLE_JIT_CONFIG = 'true'; + process.env.ENABLE_JOB_QUEUED_CHECK = 'false'; + process.env.RUNNER_LABELS = 'jit'; + process.env.SSM_TOKEN_PATH = '/github-action-runners/default/runners/config'; + await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); + expect(mockOctokit.actions.getJobForWorkflowRun).not.toBeCalled(); + expect(createRunner).toBeCalledWith(expectedRunnerParams); + + expect(mockSSMClient).toHaveReceivedNthSpecificCommandWith(1, PutParameterCommand, { + Name: '/github-action-runners/default/runners/config/i-12345', + Value: '--url https://github.com/Codertocat/hello-world --token 1234abcd --labels jit', + Type: 'SecureString', + Tags: [ + { + Key: 'InstanceId', + Value: 'i-12345', + }, + ], + }); }); it('creates a ephemeral runner after checking job is queued.', async () => { @@ -570,14 +779,12 @@ describe('scaleUp with public GH', () => { process.env.ENABLE_JOB_QUEUED_CHECK = 'true'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); expect(mockOctokit.actions.getJobForWorkflowRun).toBeCalled(); - expectedRunnerParams.runnerServiceConfig = [...expectedRunnerParams.runnerServiceConfig, `--ephemeral`]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); it('disable auto update on the runner.', async () => { process.env.DISABLE_RUNNER_AUTOUPDATE = 'true'; await scaleUpModule.scaleUp('aws:sqs', TEST_DATA); - expectedRunnerParams.runnerServiceConfig = [...expectedRunnerParams.runnerServiceConfig, `--disableupdate`]; expect(createRunner).toBeCalledWith(expectedRunnerParams); }); diff --git a/lambdas/functions/control-plane/src/scale-runners/scale-up.ts b/lambdas/functions/control-plane/src/scale-runners/scale-up.ts new file mode 100644 index 0000000000..c4a841ab28 --- /dev/null +++ b/lambdas/functions/control-plane/src/scale-runners/scale-up.ts @@ -0,0 +1,418 @@ +import { Octokit } from '@octokit/rest'; +import { addPersistentContextToChildLogger, createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getParameter, putParameter } from '@terraform-aws-github-runner/aws-ssm-util'; +import yn from 'yn'; + +import { createGithubAppAuth, createGithubInstallationAuth, createOctoClient } from '../gh-auth/gh-auth'; +import { createRunner, listEC2Runners } from './../aws/runners'; +import { RunnerInputParameters } from './../aws/runners.d'; +import ScaleError from './ScaleError'; + +const logger = createChildLogger('scale-up'); + +export interface RunnerGroup { + name: string; + id: number; +} + +interface EphemeralRunnerConfig { + runnerName: string; + runnerGroupId: number; + runnerLabels: string[]; +} + +export interface ActionRequestMessage { + id: number; + eventType: 'check_run' | 'workflow_job'; + repositoryName: string; + repositoryOwner: string; + installationId: number; +} + +interface CreateGitHubRunnerConfig { + ephemeral: boolean; + ghesBaseUrl: string; + enableJitConfig: boolean; + runnerLabels: string; + runnerGroup: string; + runnerNamePrefix: string; + runnerOwner: string; + runnerType: 'Org' | 'Repo'; + disableAutoUpdate: boolean; + ssmTokenPath: string; + ssmConfigPath: string; +} + +interface CreateEC2RunnerConfig { + environment: string; + subnets: string[]; + launchTemplateName: string; + ec2instanceCriteria: RunnerInputParameters['ec2instanceCriteria']; + numberOfRunners?: number; + amiIdSsmParameterName?: string; + tracingEnabled?: boolean; + onDemandFailoverOnError?: string[]; +} + +function generateRunnerServiceConfig(githubRunnerConfig: CreateGitHubRunnerConfig, token: string) { + const config = [ + `--url ${githubRunnerConfig.ghesBaseUrl ?? 'https://github.com'}/${githubRunnerConfig.runnerOwner}`, + `--token ${token}`, + ]; + + if (githubRunnerConfig.runnerLabels) { + config.push(`--labels ${githubRunnerConfig.runnerLabels}`.trim()); + } + + if (githubRunnerConfig.disableAutoUpdate) { + config.push('--disableupdate'); + } + + if (githubRunnerConfig.runnerType === 'Org' && githubRunnerConfig.runnerGroup !== undefined) { + config.push(`--runnergroup ${githubRunnerConfig.runnerGroup}`); + } + + if (githubRunnerConfig.ephemeral) { + config.push(`--ephemeral`); + } + + return config; +} + +async function getGithubRunnerRegistrationToken(githubRunnerConfig: CreateGitHubRunnerConfig, ghClient: Octokit) { + const registrationToken = + githubRunnerConfig.runnerType === 'Org' + ? await ghClient.actions.createRegistrationTokenForOrg({ org: githubRunnerConfig.runnerOwner }) + : await ghClient.actions.createRegistrationTokenForRepo({ + owner: githubRunnerConfig.runnerOwner.split('/')[0], + repo: githubRunnerConfig.runnerOwner.split('/')[1], + }); + return registrationToken.data.token; +} + +function removeTokenFromLogging(config: string[]): string[] { + const result: string[] = []; + config.forEach((e) => { + if (e.startsWith('--token')) { + result.push('--token '); + } else { + result.push(e); + } + }); + return result; +} + +async function getInstallationId( + ghesApiUrl: string, + enableOrgLevel: boolean, + payload: ActionRequestMessage, +): Promise { + if (payload.installationId !== 0) { + return payload.installationId; + } + + const ghAuth = await createGithubAppAuth(undefined, ghesApiUrl); + const githubClient = await createOctoClient(ghAuth.token, ghesApiUrl); + return enableOrgLevel + ? ( + await githubClient.apps.getOrgInstallation({ + org: payload.repositoryOwner, + }) + ).data.id + : ( + await githubClient.apps.getRepoInstallation({ + owner: payload.repositoryOwner, + repo: payload.repositoryName, + }) + ).data.id; +} + +async function isJobQueued(githubInstallationClient: Octokit, payload: ActionRequestMessage): Promise { + let isQueued = false; + if (payload.eventType === 'workflow_job') { + const jobForWorkflowRun = await githubInstallationClient.actions.getJobForWorkflowRun({ + job_id: payload.id, + owner: payload.repositoryOwner, + repo: payload.repositoryName, + }); + isQueued = jobForWorkflowRun.data.status === 'queued'; + } else { + throw Error(`Event ${payload.eventType} is not supported`); + } + if (!isQueued) { + logger.warn(`Job not queued in GitHub. A new runner instance will NOT be created for this job.`); + } + return isQueued; +} + +async function getRunnerGroupId(githubRunnerConfig: CreateGitHubRunnerConfig, ghClient: Octokit): Promise { + // if the runnerType is Repo, then runnerGroupId is default to 1 + let runnerGroupId: number | undefined = 1; + if (githubRunnerConfig.runnerType === 'Org' && githubRunnerConfig.runnerGroup !== undefined) { + let runnerGroup: string | undefined; + // check if runner group id is already stored in SSM Parameter Store and + // use it if it exists to avoid API call to GitHub + try { + runnerGroup = await getParameter( + `${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}`, + ); + } catch (err) { + logger.debug('Handling error:', err as Error); + logger.warn( + `SSM Parameter "${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}" + for Runner group ${githubRunnerConfig.runnerGroup} does not exist`, + ); + } + if (runnerGroup === undefined) { + // get runner group id from GitHub + runnerGroupId = await GetRunnerGroupByName(ghClient, githubRunnerConfig); + // store runner group id in SSM + try { + await putParameter( + `${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}`, + runnerGroupId.toString(), + false, + ); + } catch (err) { + logger.debug('Error storing runner group id in SSM Parameter Store', err as Error); + throw err; + } + } else { + runnerGroupId = parseInt(runnerGroup); + } + } + return runnerGroupId; +} + +async function GetRunnerGroupByName(ghClient: Octokit, githubRunnerConfig: CreateGitHubRunnerConfig): Promise { + const runnerGroups: RunnerGroup[] = await ghClient.paginate(`GET /orgs/{org}/actions/runner-groups`, { + org: githubRunnerConfig.runnerOwner, + per_page: 100, + }); + const runnerGroupId = runnerGroups.find((runnerGroup) => runnerGroup.name === githubRunnerConfig.runnerGroup)?.id; + + if (runnerGroupId === undefined) { + throw new Error(`Runner group ${githubRunnerConfig.runnerGroup} does not exist`); + } + + return runnerGroupId; +} + +export async function createRunners( + githubRunnerConfig: CreateGitHubRunnerConfig, + ec2RunnerConfig: CreateEC2RunnerConfig, + ghClient: Octokit, +): Promise { + const instances = await createRunner({ + runnerType: githubRunnerConfig.runnerType, + runnerOwner: githubRunnerConfig.runnerOwner, + numberOfRunners: 1, + ...ec2RunnerConfig, + }); + if (instances.length !== 0) { + await createStartRunnerConfig(githubRunnerConfig, instances, ghClient); + } +} + +export async function scaleUp(eventSource: string, payload: ActionRequestMessage): Promise { + logger.info(`Received ${payload.eventType} from ${payload.repositoryOwner}/${payload.repositoryName}`); + + if (eventSource !== 'aws:sqs') throw Error('Cannot handle non-SQS events!'); + const enableOrgLevel = yn(process.env.ENABLE_ORGANIZATION_RUNNERS, { default: true }); + const maximumRunners = parseInt(process.env.RUNNERS_MAXIMUM_COUNT || '3'); + const runnerLabels = process.env.RUNNER_LABELS || ''; + const runnerGroup = process.env.RUNNER_GROUP_NAME || 'Default'; + const environment = process.env.ENVIRONMENT; + const ghesBaseUrl = process.env.GHES_URL; + const ssmTokenPath = process.env.SSM_TOKEN_PATH; + const subnets = process.env.SUBNET_IDS.split(','); + const instanceTypes = process.env.INSTANCE_TYPES.split(','); + const instanceTargetCapacityType = process.env.INSTANCE_TARGET_CAPACITY_TYPE; + const ephemeralEnabled = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false }); + const enableJitConfig = yn(process.env.ENABLE_JIT_CONFIG, { default: ephemeralEnabled }); + const disableAutoUpdate = yn(process.env.DISABLE_RUNNER_AUTOUPDATE, { default: false }); + const launchTemplateName = process.env.LAUNCH_TEMPLATE_NAME; + const instanceMaxSpotPrice = process.env.INSTANCE_MAX_SPOT_PRICE; + const instanceAllocationStrategy = process.env.INSTANCE_ALLOCATION_STRATEGY || 'lowest-price'; // same as AWS default + const enableJobQueuedCheck = yn(process.env.ENABLE_JOB_QUEUED_CHECK, { default: true }); + const amiIdSsmParameterName = process.env.AMI_ID_SSM_PARAMETER_NAME; + const runnerNamePrefix = process.env.RUNNER_NAME_PREFIX || ''; + const ssmConfigPath = process.env.SSM_CONFIG_PATH || ''; + const tracingEnabled = yn(process.env.POWERTOOLS_TRACE_ENABLED, { default: false }); + const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS + ? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string]) + : []; + + if (ephemeralEnabled && payload.eventType !== 'workflow_job') { + logger.warn(`${payload.eventType} event is not supported in combination with ephemeral runners.`); + throw Error( + `The event type ${payload.eventType} is not supported in combination with ephemeral runners.` + + `Please ensure you have enabled workflow_job events.`, + ); + } + const ephemeral = ephemeralEnabled && payload.eventType === 'workflow_job'; + const runnerType = enableOrgLevel ? 'Org' : 'Repo'; + const runnerOwner = enableOrgLevel ? payload.repositoryOwner : `${payload.repositoryOwner}/${payload.repositoryName}`; + + addPersistentContextToChildLogger({ + runner: { + type: runnerType, + owner: runnerOwner, + namePrefix: runnerNamePrefix, + }, + github: { + event: payload.eventType, + workflow_job_id: payload.id.toString(), + }, + }); + + logger.info(`Received event`); + + let ghesApiUrl = ''; + if (ghesBaseUrl) { + ghesApiUrl = `${ghesBaseUrl}/api/v3`; + } + + const installationId = await getInstallationId(ghesApiUrl, enableOrgLevel, payload); + const ghAuth = await createGithubInstallationAuth(installationId, ghesApiUrl); + const githubInstallationClient = await createOctoClient(ghAuth.token, ghesApiUrl); + if (!enableJobQueuedCheck || (await isJobQueued(githubInstallationClient, payload))) { + let scaleUp = true; + if (maximumRunners !== -1) { + const currentRunners = await listEC2Runners({ + environment, + runnerType, + runnerOwner, + }); + logger.info(`Current runners: ${currentRunners.length} of ${maximumRunners}`); + scaleUp = currentRunners.length < maximumRunners; + } + + if (scaleUp) { + logger.info(`Attempting to launch a new runner`); + + await createRunners( + { + ephemeral, + enableJitConfig, + ghesBaseUrl, + runnerLabels, + runnerGroup, + runnerNamePrefix, + runnerOwner, + runnerType, + disableAutoUpdate, + ssmTokenPath, + ssmConfigPath, + }, + { + ec2instanceCriteria: { + instanceTypes, + targetCapacityType: instanceTargetCapacityType, + maxSpotPrice: instanceMaxSpotPrice, + instanceAllocationStrategy: instanceAllocationStrategy, + }, + environment, + launchTemplateName, + subnets, + amiIdSsmParameterName, + tracingEnabled, + onDemandFailoverOnError, + }, + githubInstallationClient, + ); + } else { + logger.info('No runner will be created, maximum number of runners reached.'); + if (ephemeral) { + throw new ScaleError('No runners create: maximum of runners reached.'); + } + } + } +} +async function createStartRunnerConfig( + githubRunnerConfig: CreateGitHubRunnerConfig, + instances: string[], + ghClient: Octokit, +) { + if (githubRunnerConfig.enableJitConfig && githubRunnerConfig.ephemeral) { + await createJitConfig(githubRunnerConfig, instances, ghClient); + } else { + await createRegistrationTokenConfig(githubRunnerConfig, instances, ghClient); + } +} + +function addDelay(instances: string[]) { + const delay = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + const ssmParameterStoreMaxThroughput = 40; + const isDelay = instances.length >= ssmParameterStoreMaxThroughput; + return { isDelay, delay }; +} + +async function createRegistrationTokenConfig( + githubRunnerConfig: CreateGitHubRunnerConfig, + instances: string[], + ghClient: Octokit, +) { + const { isDelay, delay } = addDelay(instances); + const token = await getGithubRunnerRegistrationToken(githubRunnerConfig, ghClient); + const runnerServiceConfig = generateRunnerServiceConfig(githubRunnerConfig, token); + + logger.debug('Runner service config for non-ephemeral runners', { + runner_service_config: removeTokenFromLogging(runnerServiceConfig), + }); + + for (const instance of instances) { + await putParameter(`${githubRunnerConfig.ssmTokenPath}/${instance}`, runnerServiceConfig.join(' '), true, { + tags: [{ Key: 'InstanceId', Value: instance }], + }); + if (isDelay) { + // Delay to prevent AWS ssm rate limits by being within the max throughput limit + await delay(25); + } + } +} + +async function createJitConfig(githubRunnerConfig: CreateGitHubRunnerConfig, instances: string[], ghClient: Octokit) { + const runnerGroupId = await getRunnerGroupId(githubRunnerConfig, ghClient); + const { isDelay, delay } = addDelay(instances); + const runnerLabels = githubRunnerConfig.runnerLabels.split(','); + + logger.debug(`Runner group id: ${runnerGroupId}`); + logger.debug(`Runner labels: ${runnerLabels}`); + for (const instance of instances) { + // generate jit config for runner registration + const ephemeralRunnerConfig: EphemeralRunnerConfig = { + runnerName: `${githubRunnerConfig.runnerNamePrefix}${instance}`, + runnerGroupId: runnerGroupId, + runnerLabels: runnerLabels, + }; + logger.debug(`Runner name: ${ephemeralRunnerConfig.runnerName}`); + const runnerConfig = + githubRunnerConfig.runnerType === 'Org' + ? await ghClient.actions.generateRunnerJitconfigForOrg({ + org: githubRunnerConfig.runnerOwner, + name: ephemeralRunnerConfig.runnerName, + runner_group_id: ephemeralRunnerConfig.runnerGroupId, + labels: ephemeralRunnerConfig.runnerLabels, + }) + : await ghClient.actions.generateRunnerJitconfigForRepo({ + owner: githubRunnerConfig.runnerOwner.split('/')[0], + repo: githubRunnerConfig.runnerOwner.split('/')[1], + name: ephemeralRunnerConfig.runnerName, + runner_group_id: ephemeralRunnerConfig.runnerGroupId, + labels: ephemeralRunnerConfig.runnerLabels, + }); + + // store jit config in ssm parameter store + logger.debug('Runner JIT config for ephemeral runner generated.', { + instance: instance, + }); + await putParameter(`${githubRunnerConfig.ssmTokenPath}/${instance}`, runnerConfig.data.encoded_jit_config, true, { + tags: [{ Key: 'InstanceId', Value: instance }], + }); + if (isDelay) { + // Delay to prevent AWS ssm rate limits by being within the max throughput limit + await delay(25); + } + } +} diff --git a/lambdas/functions/control-plane/src/scale-runners/ssm-housekeeper.test.ts b/lambdas/functions/control-plane/src/scale-runners/ssm-housekeeper.test.ts new file mode 100644 index 0000000000..3af60b27e6 --- /dev/null +++ b/lambdas/functions/control-plane/src/scale-runners/ssm-housekeeper.test.ts @@ -0,0 +1,117 @@ +import { DeleteParameterCommand, GetParametersByPathCommand, SSMClient } from '@aws-sdk/client-ssm'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; +import { cleanSSMTokens } from './ssm-housekeeper'; + +process.env.AWS_REGION = 'eu-east-1'; + +const mockSSMClient = mockClient(SSMClient); + +const deleteAmisOlderThenDays = 1; +const now = new Date(); +const dateOld = new Date(); +dateOld.setDate(dateOld.getDate() - deleteAmisOlderThenDays - 1); + +const tokenPath = '/path/to/tokens/'; + +describe('clean SSM tokens / JIT config', () => { + beforeEach(() => { + mockSSMClient.reset(); + mockSSMClient.on(GetParametersByPathCommand).resolves({ + Parameters: undefined, + }); + mockSSMClient.on(GetParametersByPathCommand, { Path: tokenPath }).resolves({ + Parameters: [ + { + Name: tokenPath + 'i-old-01', + LastModifiedDate: dateOld, + }, + ], + NextToken: 'next', + }); + mockSSMClient.on(GetParametersByPathCommand, { Path: tokenPath, NextToken: 'next' }).resolves({ + Parameters: [ + { + Name: tokenPath + 'i-new-01', + LastModifiedDate: now, + }, + ], + NextToken: undefined, + }); + }); + + it('should delete parameters older then minimumDaysOld', async () => { + await cleanSSMTokens({ + dryRun: false, + minimumDaysOld: deleteAmisOlderThenDays, + tokenPath: tokenPath, + }); + + expect(mockSSMClient).toHaveReceivedCommandWith(GetParametersByPathCommand, { Path: tokenPath }); + expect(mockSSMClient).toHaveReceivedCommandWith(DeleteParameterCommand, { Name: tokenPath + 'i-old-01' }); + expect(mockSSMClient).not.toHaveReceivedCommandWith(DeleteParameterCommand, { Name: tokenPath + 'i-new-01' }); + }); + + it('should not delete when dry run is activated', async () => { + await cleanSSMTokens({ + dryRun: true, + minimumDaysOld: deleteAmisOlderThenDays, + tokenPath: tokenPath, + }); + + expect(mockSSMClient).toHaveReceivedCommandWith(GetParametersByPathCommand, { Path: tokenPath }); + expect(mockSSMClient).not.toHaveReceivedCommandWith(DeleteParameterCommand, { Name: tokenPath + 'i-old-01' }); + expect(mockSSMClient).not.toHaveReceivedCommandWith(DeleteParameterCommand, { Name: tokenPath + 'i-new-01' }); + }); + + it('should not call delete when no parameters are found.', async () => { + await expect( + cleanSSMTokens({ + dryRun: false, + minimumDaysOld: deleteAmisOlderThenDays, + tokenPath: 'no-exist', + }), + ).resolves.not.toThrow(); + + expect(mockSSMClient).not.toHaveReceivedCommandWith(DeleteParameterCommand, { Name: tokenPath + 'i-old-01' }); + expect(mockSSMClient).not.toHaveReceivedCommandWith(DeleteParameterCommand, { Name: tokenPath + 'i-new-01' }); + }); + + it('should not error on delete failure.', async () => { + mockSSMClient.on(DeleteParameterCommand).rejects(new Error('ParameterNotFound')); + + await expect( + cleanSSMTokens({ + dryRun: false, + minimumDaysOld: deleteAmisOlderThenDays, + tokenPath: tokenPath, + }), + ).resolves.not.toThrow(); + }); + + it('should only accept valid options.', async () => { + await expect( + cleanSSMTokens({ + dryRun: false, + minimumDaysOld: undefined as unknown as number, + tokenPath: tokenPath, + }), + ).rejects.toBeInstanceOf(Error); + + await expect( + cleanSSMTokens({ + dryRun: false, + minimumDaysOld: 0, + tokenPath: tokenPath, + }), + ).rejects.toBeInstanceOf(Error); + + await expect( + cleanSSMTokens({ + dryRun: false, + minimumDaysOld: 1, + tokenPath: undefined as unknown as string, + }), + ).rejects.toBeInstanceOf(Error); + }); +}); diff --git a/lambdas/functions/control-plane/src/scale-runners/ssm-housekeeper.ts b/lambdas/functions/control-plane/src/scale-runners/ssm-housekeeper.ts new file mode 100644 index 0000000000..78d015c921 --- /dev/null +++ b/lambdas/functions/control-plane/src/scale-runners/ssm-housekeeper.ts @@ -0,0 +1,62 @@ +import { DeleteParameterCommand, GetParametersByPathCommand, SSMClient } from '@aws-sdk/client-ssm'; +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getTracedAWSV3Client } from '@terraform-aws-github-runner/aws-powertools-util'; + +export interface SSMCleanupOptions { + dryRun: boolean; + minimumDaysOld: number; + tokenPath: string; +} + +function validateOptions(options: SSMCleanupOptions): void { + const errorMessages: string[] = []; + if (!options.minimumDaysOld || options.minimumDaysOld < 1) { + errorMessages.push(`minimumDaysOld must be greater then 0, value is set to "${options.minimumDaysOld}"`); + } + if (!options.tokenPath) { + errorMessages.push('tokenPath must be defined'); + } + if (errorMessages.length > 0) { + throw new Error(errorMessages.join(', ')); + } +} + +export async function cleanSSMTokens(options: SSMCleanupOptions): Promise { + logger.info(`Cleaning tokens / JIT config older then ${options.minimumDaysOld} days, dryRun: ${options.dryRun}`); + logger.debug('Cleaning with options', { options }); + validateOptions(options); + + const client = getTracedAWSV3Client(new SSMClient({ region: process.env.AWS_REGION })); + const parameters = await client.send(new GetParametersByPathCommand({ Path: options.tokenPath })); + while (parameters.NextToken) { + const nextParameters = await client.send( + new GetParametersByPathCommand({ Path: options.tokenPath, NextToken: parameters.NextToken }), + ); + parameters.Parameters?.push(...(nextParameters.Parameters ?? [])); + parameters.NextToken = nextParameters.NextToken; + } + logger.info(`Found #${parameters.Parameters?.length} parameters in path ${options.tokenPath}`); + logger.debug('Found parameters', { parameters }); + + // minimumDate = today - minimumDaysOld + const minimumDate = new Date(); + minimumDate.setDate(minimumDate.getDate() - options.minimumDaysOld); + + for (const parameter of parameters.Parameters ?? []) { + if (parameter.LastModifiedDate && new Date(parameter.LastModifiedDate) < minimumDate) { + logger.info(`Deleting parameter ${parameter.Name} with last modified date ${parameter.LastModifiedDate}`); + try { + if (!options.dryRun) { + // sleep 50ms to avoid rait limit + await new Promise((resolve) => setTimeout(resolve, 50)); + await client.send(new DeleteParameterCommand({ Name: parameter.Name })); + } + } catch (e) { + logger.warn(`Failed to delete parameter ${parameter.Name} with error ${(e as Error).message}`); + logger.debug('Failed to delete parameter', { e }); + } + } else { + logger.debug(`Skipping parameter ${parameter.Name} with last modified date ${parameter.LastModifiedDate}`); + } + } +} diff --git a/modules/runners/lambdas/runners/test/resources/sqs_receive_event.json b/lambdas/functions/control-plane/test/resources/sqs_receive_event.json similarity index 100% rename from modules/runners/lambdas/runners/test/resources/sqs_receive_event.json rename to lambdas/functions/control-plane/test/resources/sqs_receive_event.json diff --git a/lambdas/functions/control-plane/tsconfig.json b/lambdas/functions/control-plane/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/functions/control-plane/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.gitignore b/lambdas/functions/gh-agent-syncer/.gitignore similarity index 100% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.gitignore rename to lambdas/functions/gh-agent-syncer/.gitignore diff --git a/lambdas/functions/gh-agent-syncer/README.md b/lambdas/functions/gh-agent-syncer/README.md new file mode 100644 index 0000000000..11461b3717 --- /dev/null +++ b/lambdas/functions/gh-agent-syncer/README.md @@ -0,0 +1,3 @@ +# Lambda runner binary syncer + +For testing the lambda locally check out [this guide](../../../docs/test-lambda-local.md). diff --git a/lambdas/functions/gh-agent-syncer/jest.config.ts b/lambdas/functions/gh-agent-syncer/jest.config.ts new file mode 100644 index 0000000000..3df3730308 --- /dev/null +++ b/lambdas/functions/gh-agent-syncer/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 98, + branches: 85, + functions: 90, + lines: 98, + }, + }, +}; + +export default config; diff --git a/lambdas/functions/gh-agent-syncer/package.json b/lambdas/functions/gh-agent-syncer/package.json new file mode 100644 index 0000000000..804ee5255f --- /dev/null +++ b/lambdas/functions/gh-agent-syncer/package.json @@ -0,0 +1,59 @@ +{ + "name": "@terraform-aws-github-runner/gh-agent-syncer", + "version": "1.0.0", + "main": "lambda.ts", + "license": "MIT", + "scripts": { + "start": "ts-node-dev src/local.ts", + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "watch": "ts-node-dev --respawn --exit-child src/local.ts", + "build": "ncc build src/lambda.ts -o dist", + "dist": "yarn build && cd dist && zip ../runner-binaries-syncer.zip index.js", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@octokit/rest": "^20.0.1", + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/jest": "^29.5.12", + "@types/node": "^20.8.9", + "@types/request": "^2.48.11", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "^0.38.1", + "aws-sdk-client-mock": "^3.0.0", + "aws-sdk-client-mock-jest": "^3.0.0", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node-dev": "^2.0.0", + "typescript": "^5.4.5" + }, + "dependencies": { + "@aws-sdk/client-s3": "^3.600.0", + "@aws-sdk/lib-storage": "^3.600.0", + "@aws-sdk/types": "^3.433.0", + "@middy/core": "^4.7.0", + "@terraform-aws-github-runner/aws-powertools-util": "*", + "axios": "^1.6.8" + }, + "nx": { + "includedScripts": [ + "build", + "dist", + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/response.json b/lambdas/functions/gh-agent-syncer/response.json similarity index 100% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/response.json rename to lambdas/functions/gh-agent-syncer/response.json diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.test.ts b/lambdas/functions/gh-agent-syncer/src/lambda.test.ts similarity index 51% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.test.ts rename to lambdas/functions/gh-agent-syncer/src/lambda.test.ts index e136792806..b47b25c303 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.test.ts +++ b/lambdas/functions/gh-agent-syncer/src/lambda.test.ts @@ -1,3 +1,4 @@ +import { Context } from 'aws-lambda'; import { mocked } from 'jest-mock'; import { handler } from './lambda'; @@ -5,6 +6,27 @@ import { sync } from './syncer/syncer'; jest.mock('./syncer/syncer'); +const context: Context = { + awsRequestId: '1', + callbackWaitsForEmptyEventLoop: false, + functionName: 'unit-test', + functionVersion: '', + getRemainingTimeInMillis: () => 0, + invokedFunctionArn: '', + logGroupName: '', + logStreamName: '', + memoryLimitInMB: '', + done: () => { + return; + }, + fail: () => { + return; + }, + succeed: () => { + return; + }, +}; + describe('Test download sync wrapper.', () => { it('Test successful download.', async () => { const mock = mocked(sync); @@ -13,13 +35,13 @@ describe('Test download sync wrapper.', () => { resolve(); }); }); - await expect(handler({}, {})).resolves; + await expect(handler({}, context)).resolves; }); it('Test wrapper with returning an error. ', async () => { const mock = mocked(sync); mock.mockRejectedValue(new Error('')); - await expect(handler({}, {})).resolves; + await expect(handler({}, context)).resolves; }); }); diff --git a/lambdas/functions/gh-agent-syncer/src/lambda.ts b/lambdas/functions/gh-agent-syncer/src/lambda.ts new file mode 100644 index 0000000000..7925d279c0 --- /dev/null +++ b/lambdas/functions/gh-agent-syncer/src/lambda.ts @@ -0,0 +1,23 @@ +import middy from '@middy/core'; +import { logger, setContext } from '@terraform-aws-github-runner/aws-powertools-util'; +import { captureLambdaHandler, tracer } from '@terraform-aws-github-runner/aws-powertools-util'; +import { Context } from 'aws-lambda'; + +import { sync } from './syncer/syncer'; + +middy(handler).use(captureLambdaHandler(tracer)); + +// eslint-disable-next-line +export async function handler(event: any, context: Context): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + + try { + await sync(); + } catch (e) { + if (e instanceof Error) { + logger.warn(`Ignoring error: ${e.message}`); + } + logger.debug('Ignoring error', { error: e }); + } +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/local.ts b/lambdas/functions/gh-agent-syncer/src/local.ts similarity index 54% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/local.ts rename to lambdas/functions/gh-agent-syncer/src/local.ts index fc6610c263..85b86194a6 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/local.ts +++ b/lambdas/functions/gh-agent-syncer/src/local.ts @@ -1,4 +1,5 @@ -import { logger } from './syncer/logger'; +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; + import { sync } from './syncer/syncer'; sync() @@ -7,5 +8,5 @@ sync() if (e instanceof Error) { logger.error(e.message); } - logger.trace(e); + logger.debug('Ignoring error', { error: e }); }); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/syncer.test.ts b/lambdas/functions/gh-agent-syncer/src/syncer/syncer.test.ts similarity index 62% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/syncer.test.ts rename to lambdas/functions/gh-agent-syncer/src/syncer/syncer.test.ts index 98511498f1..9367e3fa6a 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/syncer.test.ts +++ b/lambdas/functions/gh-agent-syncer/src/syncer/syncer.test.ts @@ -1,3 +1,6 @@ +import { GetObjectTaggingCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; import axios from 'axios'; import { PassThrough } from 'stream'; @@ -21,20 +24,13 @@ mockStream.push(mockResponse); mockStream.end(); jest.mock('axios'); -const mockedAxios = axios as jest.Mocked; -mockedAxios.request.mockResolvedValue({ +const mockAxios = axios as jest.Mocked; +mockAxios.get.mockResolvedValue({ data: mockStream, }); -const mockS3 = { - getObjectTagging: jest.fn(), - upload: jest.fn().mockImplementation(() => { - return { promise: jest.fn(() => Promise.resolve()) }; - }), -}; -jest.mock('aws-sdk', () => ({ - S3: jest.fn().mockImplementation(() => mockS3), -})); +process.env.AWS_REGION = 'us-east-1'; +const mockS3client = mockClient(S3Client); const bucketName = 'my-bucket'; const objectExtension: Record = { @@ -54,6 +50,7 @@ const latestRelease = '2.296.2'; beforeEach(() => { jest.clearAllMocks(); + mockS3client.reset(); }); jest.setTimeout(60 * 1000); @@ -61,7 +58,6 @@ jest.setTimeout(60 * 1000); describe('Synchronize action distribution (no S3 tags).', () => { beforeEach(() => { process.env.S3_BUCKET_NAME = bucketName; - mockOctokit.repos.getLatestRelease.mockImplementation(() => ({ data: mockDataLatestRelease, })); @@ -70,25 +66,19 @@ describe('Synchronize action distribution (no S3 tags).', () => { test.each(runnerOs)('%p Distribution is S3 has no tags.', async (os) => { process.env.S3_OBJECT_KEY = bucketObjectKey(os); process.env.GITHUB_RUNNER_OS = os; - mockS3.getObjectTagging.mockImplementation(() => { - return { - promise() { - return Promise.resolve({ - TagSet: undefined, - }); - }, - }; + mockS3client.on(GetObjectTaggingCommand).resolves({ + TagSet: undefined, }); await sync(); - expect(mockS3.upload).toBeCalledTimes(1); + expect(mockS3client).toHaveReceivedCommandTimes(PutObjectCommand, 1); }); }); -describe('Synchronize action distribution (up-to-date).', () => { +describe('Synchronize action distribution.', () => { beforeEach(() => { process.env.S3_BUCKET_NAME = bucketName; - + mockS3client.reset(); mockOctokit.repos.getLatestRelease.mockImplementation(() => ({ data: mockDataLatestRelease, })); @@ -97,67 +87,81 @@ describe('Synchronize action distribution (up-to-date).', () => { test.each(runnerOs)('%p Distribution is up-to-date with latest release.', async (os) => { process.env.S3_OBJECT_KEY = bucketObjectKey(os); process.env.GITHUB_RUNNER_OS = os; - mockS3.getObjectTagging.mockImplementation(() => { - return { - promise() { - return Promise.resolve({ - TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}` }], - }); - }, - }; + mockS3client.on(GetObjectTaggingCommand).resolves({ + TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}` }], }); await sync(); expect(mockOctokit.repos.getLatestRelease).toBeCalledTimes(1); - expect(mockS3.getObjectTagging).toBeCalledWith({ + expect(mockS3client).toHaveReceivedNthCommandWith(1, GetObjectTaggingCommand, { Bucket: bucketName, Key: bucketObjectKey(os), }); - expect(mockS3.upload).toBeCalledTimes(0); + + expect(mockS3client).toHaveReceivedCommandTimes(PutObjectCommand, 0); }); test.each(runnerOs)('%p Distribution should update to release.', async (os) => { process.env.S3_OBJECT_KEY = bucketObjectKey(os); process.env.GITHUB_RUNNER_OS = os; - mockS3.getObjectTagging.mockImplementation(() => { - return { - promise() { - return Promise.resolve({ - TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-0${objectExtension[os]}` }], - }); - }, - }; + + mockS3client.on(GetObjectTaggingCommand).resolves({ + TagSet: [{ Key: 'name', Value: `actions-runner-${os}-x64-0${objectExtension[os]}` }], }); await sync(); expect(mockOctokit.repos.getLatestRelease).toBeCalledTimes(1); - expect(mockS3.getObjectTagging).toBeCalledWith({ + expect(mockS3client).toHaveReceivedNthCommandWith(1, GetObjectTaggingCommand, { Bucket: bucketName, Key: bucketObjectKey(os), }); - expect(mockS3.upload).toBeCalledTimes(1); - const s3JsonBody = mockS3.upload.mock.calls[0][0]; - expect(s3JsonBody['Tagging']).toEqual(`name=actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}`); + + expect(mockS3client).toHaveReceivedNthSpecificCommandWith(1, PutObjectCommand, { + Bucket: bucketName, + Key: bucketObjectKey(os), + Tagging: `name=actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}`, + }); + }); + + test.each(runnerOs)('%p Distribution should update to release (tags look-up errored)', async (os) => { + process.env.S3_OBJECT_KEY = bucketObjectKey(os); + process.env.GITHUB_RUNNER_OS = os; + + mockS3client.on(GetObjectTaggingCommand).rejects(new Error('No tags')); + + await sync(); + expect(mockOctokit.repos.getLatestRelease).toBeCalledTimes(1); + expect(mockS3client).toHaveReceivedNthCommandWith(1, GetObjectTaggingCommand, { + Bucket: bucketName, + Key: bucketObjectKey(os), + }); + + expect(mockS3client).toHaveReceivedNthSpecificCommandWith(1, PutObjectCommand, { + Bucket: bucketName, + Key: bucketObjectKey(os), + Tagging: `name=actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}`, + }); }); test.each(runnerOs)('%p Tags, but no version, distribution should update.', async (os) => { process.env.S3_OBJECT_KEY = bucketObjectKey(os); process.env.GITHUB_RUNNER_OS = os; - mockS3.getObjectTagging.mockImplementation(() => { - return { - promise() { - return Promise.resolve({ TagSet: [{ Key: 'someKey', Value: 'someValue' }] }); - }, - }; + mockS3client.on(GetObjectTaggingCommand).resolves({ + TagSet: [{ Key: 'someKey', Value: `someValue` }], }); await sync(); expect(mockOctokit.repos.getLatestRelease).toBeCalledTimes(1); - expect(mockS3.getObjectTagging).toBeCalledWith({ + expect(mockS3client).toHaveReceivedNthCommandWith(1, GetObjectTaggingCommand, { + Bucket: bucketName, + Key: bucketObjectKey(os), + }); + + expect(mockS3client).toHaveReceivedNthSpecificCommandWith(1, PutObjectCommand, { Bucket: bucketName, Key: bucketObjectKey(os), + Tagging: `name=actions-runner-${os}-x64-${latestRelease}${objectExtension[os]}`, }); - expect(mockS3.upload).toBeCalledTimes(1); }); }); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/syncer.ts b/lambdas/functions/gh-agent-syncer/src/syncer/syncer.ts similarity index 51% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/syncer.ts rename to lambdas/functions/gh-agent-syncer/src/syncer/syncer.ts index 4dceaa25a5..d25b1c97e0 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/syncer.ts +++ b/lambdas/functions/gh-agent-syncer/src/syncer/syncer.ts @@ -1,30 +1,30 @@ +import { GetObjectTaggingCommand, S3Client, ServerSideEncryption, Tag } from '@aws-sdk/client-s3'; +import { Upload } from '@aws-sdk/lib-storage'; import { Octokit } from '@octokit/rest'; -import { S3 } from 'aws-sdk'; -import AWS from 'aws-sdk'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { getTracedAWSV3Client } from '@terraform-aws-github-runner/aws-powertools-util'; import axios from 'axios'; -import { PassThrough } from 'stream'; - -import { logger as rootLogger } from './logger'; - -const logger = rootLogger.getChildLogger(); +import { Stream } from 'stream'; const versionKey = 'name'; +const logger = createChildLogger('syncer.ts'); + interface CacheObject { bucket: string; key: string; } -async function getCachedVersion(s3: S3, cacheObject: CacheObject): Promise { +async function getCachedVersion(s3Client: S3Client, cacheObject: CacheObject): Promise { + const command = new GetObjectTaggingCommand({ + Bucket: cacheObject.bucket, + Key: cacheObject.key, + }); + try { - const objectTagging = await s3 - .getObjectTagging({ - Bucket: cacheObject.bucket, - Key: cacheObject.key, - }) - .promise(); - const versions = objectTagging.TagSet?.filter((t: S3.Tag) => t.Key === versionKey); - return versions.length === 1 ? versions[0].Value : undefined; + const objectTagging = await s3Client.send(command); + const versions = objectTagging.TagSet?.filter((t: Tag) => t.Key === versionKey); + return versions?.length === 1 ? versions[0].Value : undefined; } catch (e) { logger.debug('No tags found'); return undefined; @@ -53,48 +53,39 @@ async function getReleaseAsset(runnerOs = 'linux', runnerArch = 'x64'): Promise< return assets?.length === 1 ? { name: assets[0].name, downloadUrl: assets[0].browser_download_url } : undefined; } -async function uploadToS3(s3: S3, cacheObject: CacheObject, actionRunnerReleaseAsset: ReleaseAsset): Promise { - const writeStream = new PassThrough(); - const writePromise = s3 - .upload({ +async function uploadToS3( + s3Client: S3Client, + cacheObject: CacheObject, + actionRunnerReleaseAsset: ReleaseAsset, +): Promise { + const response = await axios.get(actionRunnerReleaseAsset.downloadUrl, { + responseType: 'stream', + }); + + const passThrough = new Stream.PassThrough(); + response.data.pipe(passThrough); + + const upload = new Upload({ + client: s3Client, + params: { Bucket: cacheObject.bucket, Key: cacheObject.key, Tagging: versionKey + '=' + actionRunnerReleaseAsset.name, - Body: writeStream, - ServerSideEncryption: process.env.S3_SSE_ALGORITHM, - SSEKMSKeyId: process.env.S3_SSE_KMS_KEY_ID, - }) - .promise(); - - logger.debug('Start downloading %s and uploading to S3.', actionRunnerReleaseAsset.name); - - const readPromise = new Promise((resolve, reject) => { - axios - .request({ - method: 'get', - url: actionRunnerReleaseAsset.downloadUrl, - responseType: 'stream', - }) - .then((res) => { - res.data - .pipe(writeStream) - - .on('finish', () => resolve()) - .on('error', (error) => reject(error)); - }) - .catch((error) => reject(error)); + Body: passThrough, + ServerSideEncryption: process.env.S3_SSE_ALGORITHM as ServerSideEncryption, + }, }); - await Promise.all([readPromise, writePromise]) - .then(() => logger.info(`The new distribution is uploaded to S3.`)) - .catch((error) => { - logger.error(`Uploading of the new distribution to S3 failed: ${error}`); - throw error; - }); + upload.on('httpUploadProgress', () => logger.debug(`Downloading ${actionRunnerReleaseAsset.name} in progress`)); + logger.debug(`Start downloading ${actionRunnerReleaseAsset.name} and uploading to S3.`); + await upload + .done() + .then(() => logger.info(`The new distribution ${actionRunnerReleaseAsset.name} is uploaded to S3.`)) + .catch((e) => logger.error(`Error uploading ${actionRunnerReleaseAsset.name} to S3`, e)); } export async function sync(): Promise { - const s3 = new AWS.S3(); + const s3 = getTracedAWSV3Client(new S3Client({})); const runnerOs = process.env.GITHUB_RUNNER_OS || 'linux'; const runnerArch = process.env.GITHUB_RUNNER_ARCHITECTURE || 'x64'; @@ -116,6 +107,6 @@ export async function sync(): Promise { if (currentVersion === undefined || currentVersion != actionRunnerReleaseAsset.name) { await uploadToS3(s3, cacheObject, actionRunnerReleaseAsset); } else { - logger.debug('Distribution is up-to-date, no action.'); + logger.debug('Distribution is up-to-date, download skipped.'); } } diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/template.yaml b/lambdas/functions/gh-agent-syncer/template.yaml similarity index 89% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/template.yaml rename to lambdas/functions/gh-agent-syncer/template.yaml index bd66af9aa6..52c506ff3a 100755 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/template.yaml +++ b/lambdas/functions/gh-agent-syncer/template.yaml @@ -3,7 +3,7 @@ Resources: Syncer: Type: AWS::Serverless::Function Properties: - Runtime: nodejs16.x + Runtime: nodejs18.x Handler: dist/index.handler MemorySize: 256 Timeout: 300 @@ -12,6 +12,5 @@ Resources: GITHUB_RUNNER_ARCHITECTURE: GITHUB_RUNNER_OS: LOG_LEVEL: - LOG_TYPE: S3_BUCKET_NAME: S3_OBJECT_KEY: diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/test/resources/github-latest-release.json b/lambdas/functions/gh-agent-syncer/test/resources/github-latest-release.json similarity index 100% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/test/resources/github-latest-release.json rename to lambdas/functions/gh-agent-syncer/test/resources/github-latest-release.json diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/test/resources/github-releases-no-x64.json b/lambdas/functions/gh-agent-syncer/test/resources/github-releases-no-x64.json similarity index 100% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/test/resources/github-releases-no-x64.json rename to lambdas/functions/gh-agent-syncer/test/resources/github-releases-no-x64.json diff --git a/lambdas/functions/gh-agent-syncer/tsconfig.json b/lambdas/functions/gh-agent-syncer/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/functions/gh-agent-syncer/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/lambdas/functions/termination-watcher/jest.config.ts b/lambdas/functions/termination-watcher/jest.config.ts new file mode 100644 index 0000000000..077707f923 --- /dev/null +++ b/lambdas/functions/termination-watcher/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 100, + branches: 100, + functions: 100, + lines: 100, + }, + }, +}; + +export default config; diff --git a/lambdas/functions/termination-watcher/package.json b/lambdas/functions/termination-watcher/package.json new file mode 100644 index 0000000000..c1de99bde4 --- /dev/null +++ b/lambdas/functions/termination-watcher/package.json @@ -0,0 +1,56 @@ +{ + "name": "@terraform-aws-github-runner/termination-watcher", + "version": "1.0.0", + "main": "lambda.ts", + "license": "MIT", + "scripts": { + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "build": "ncc build src/lambda.ts -o dist", + "dist": "yarn build && cd dist && zip ../termination-watcher.zip index.js", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/jest": "^29.5.6", + "@types/node": "^20.8.9", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "^0.38.1", + "aws-sdk-client-mock": "^3.0.0", + "aws-sdk-client-mock-jest": "^3.0.0", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "jest-mock-extended": "^3.0.6", + "nock": "^13.4.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node": "^10.9.1", + "ts-node-dev": "^2.0.0" + }, + "dependencies": { + "@aws-sdk/client-ec2": "^3.604.0", + "@aws-sdk/types": "^3.433.0", + "@middy/core": "^4.7.0", + "@terraform-aws-github-runner/aws-powertools-util": "*", + "typescript": "^5.4.5" + }, + "nx": { + "includedScripts": [ + "build", + "dist", + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/lambdas/functions/termination-watcher/src/ConfigResolver.test.ts b/lambdas/functions/termination-watcher/src/ConfigResolver.test.ts new file mode 100644 index 0000000000..556b07499d --- /dev/null +++ b/lambdas/functions/termination-watcher/src/ConfigResolver.test.ts @@ -0,0 +1,57 @@ +import { Config } from './ConfigResolver'; + +process.env.ENABLE_METRICS_SPOT_WARNING = 'true'; + +describe('Test ConfigResolver', () => { + const data = [ + { + description: 'metric with tag filter', + input: { createSpotWarningMetric: true, tagFilters: '{"ghr:abc": "test"}', prefix: undefined }, + output: { createSpotWarningMetric: true, tagFilters: { 'ghr:abc': 'test' } }, + }, + { + description: 'no metric with no filter', + input: { createSpotWarningMetric: false, prefix: 'test' }, + output: { createSpotWarningMetric: false, tagFilters: { 'ghr:environment': 'test' } }, + }, + { + description: 'no metric with invalid filter', + input: { createSpotWarningMetric: false, tagFilters: '{"ghr:" "test"', prefix: 'runners' }, + output: { createSpotWarningMetric: false, tagFilters: { 'ghr:environment': 'runners' } }, + }, + { + description: 'no metric with null filter', + input: { createSpotWarningMetric: false, tagFilters: 'null', prefix: 'runners' }, + output: { createSpotWarningMetric: false, tagFilters: { 'ghr:environment': 'runners' } }, + }, + { + description: 'undefined input', + input: { createSpotWarningMetric: undefined, tagFilters: undefined, prefix: undefined }, + output: { createSpotWarningMetric: false, tagFilters: { 'ghr:environment': '' } }, + }, + ]; + + describe.each(data)('Should check configuration for: $description', ({ description, input, output }) => { + beforeEach(() => { + delete process.env.ENABLE_METRICS_SPOT_WARNING; + delete process.env.PREFIX; + delete process.env.TAG_FILTERS; + }); + + it(description, async () => { + if (input.createSpotWarningMetric !== undefined) { + process.env.ENABLE_METRICS_SPOT_WARNING = input.createSpotWarningMetric ? 'true' : 'false'; + } + if (input.tagFilters) { + process.env.TAG_FILTERS = input.tagFilters; + } + if (input.prefix) { + process.env.PREFIX = input.prefix; + } + + const config = new Config(); + expect(config.createSpotWarningMetric).toBe(output.createSpotWarningMetric); + expect(config.tagFilters).toEqual(output.tagFilters); + }); + }); +}); diff --git a/lambdas/functions/termination-watcher/src/ConfigResolver.ts b/lambdas/functions/termination-watcher/src/ConfigResolver.ts new file mode 100644 index 0000000000..e72f1d512e --- /dev/null +++ b/lambdas/functions/termination-watcher/src/ConfigResolver.ts @@ -0,0 +1,28 @@ +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; + +export class Config { + createSpotWarningMetric: boolean; + tagFilters: Record; + prefix: string; + + constructor() { + const logger = createChildLogger('config-resolver'); + + logger.debug('Loading config from environment variables', { env: process.env }); + + this.createSpotWarningMetric = process.env.ENABLE_METRICS_SPOT_WARNING === 'true'; + this.prefix = process.env.PREFIX ?? ''; + this.tagFilters = { 'ghr:environment': this.prefix }; + + const rawTagFilters = process.env.TAG_FILTERS; + if (rawTagFilters && rawTagFilters !== 'null') { + try { + this.tagFilters = JSON.parse(rawTagFilters); + } catch (e) { + logger.error('Failed to parse TAG_FILTERS', { error: e }); + } + } + + logger.debug('Loaded config', { config: this }); + } +} diff --git a/lambdas/functions/termination-watcher/src/lambda.test.ts b/lambdas/functions/termination-watcher/src/lambda.test.ts new file mode 100644 index 0000000000..3137232caa --- /dev/null +++ b/lambdas/functions/termination-watcher/src/lambda.test.ts @@ -0,0 +1,70 @@ +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { Context } from 'aws-lambda'; +import { mocked } from 'jest-mock'; + +import { handle as interruptionWarningHandlerImpl } from './termination-warning'; +import { interruptionWarning } from './lambda'; +import { SpotInterruptionWarning, SpotTerminationDetail } from './types'; + +jest.mock('./termination-warning'); + +process.env.POWERTOOLS_METRICS_NAMESPACE = 'test'; +process.env.POWERTOOLS_TRACE_ENABLED = 'true'; +const event: SpotInterruptionWarning = { + version: '0', + id: '1', + 'detail-type': 'EC2 Spot Instance Interruption Warning', + source: 'aws.ec2', + account: '123456789012', + time: '2015-11-11T21:29:54Z', + region: 'us-east-1', + resources: ['arn:aws:ec2:us-east-1b:instance/i-abcd1111'], + detail: { + 'instance-id': 'i-abcd1111', + 'instance-action': 'terminate', + }, +}; + +const context: Context = { + awsRequestId: '1', + callbackWaitsForEmptyEventLoop: false, + functionName: '', + functionVersion: '', + getRemainingTimeInMillis: () => 0, + invokedFunctionArn: '', + logGroupName: '', + logStreamName: '', + memoryLimitInMB: '', + done: () => { + return; + }, + fail: () => { + return; + }, + succeed: () => { + return; + }, +}; + +// Docs for testing async with jest: https://jestjs.io/docs/tutorial-async +describe('Handle sport termination interruption warning', () => { + it('should not throw or log in error.', async () => { + const mock = mocked(interruptionWarningHandlerImpl); + mock.mockImplementation(() => { + return new Promise((resolve) => { + resolve(); + }); + }); + expect(await interruptionWarning(event, context)).resolves; + }); + + it('should not throw only log in error in case of an exception.', async () => { + const logSpy = jest.spyOn(logger, 'error'); + const error = new Error('An error.'); + const mock = mocked(interruptionWarningHandlerImpl); + mock.mockRejectedValue(error); + await expect(interruptionWarning(event, context)).resolves.toBeUndefined(); + + expect(logSpy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/lambdas/functions/termination-watcher/src/lambda.ts b/lambdas/functions/termination-watcher/src/lambda.ts new file mode 100644 index 0000000000..d07249f572 --- /dev/null +++ b/lambdas/functions/termination-watcher/src/lambda.ts @@ -0,0 +1,49 @@ +import middy from '@middy/core'; +import { + captureLambdaHandler, + logger, + metrics, + setContext, + tracer, +} from '@terraform-aws-github-runner/aws-powertools-util'; +import { logMetrics } from '@aws-lambda-powertools/metrics'; +import { Context } from 'aws-lambda'; + +import { handle as handleTerminationWarning } from './termination-warning'; +import { SpotInterruptionWarning, SpotTerminationDetail } from './types'; +import { Config } from './ConfigResolver'; + +const config = new Config(); + +export async function interruptionWarning( + event: SpotInterruptionWarning, + context: Context, +): Promise { + setContext(context, 'lambda.ts'); + logger.logEventIfEnabled(event); + logger.debug('Configuration of the lambda', { config }); + + try { + await handleTerminationWarning(event, config); + } catch (e) { + logger.error(`${(e as Error).message}`, { error: e as Error }); + } +} + +const addMiddleware = () => { + const middleware = middy(interruptionWarning); + + const c = captureLambdaHandler(tracer); + if (c) { + logger.debug('Adding captureLambdaHandler middleware'); + middleware.use(c); + } + + const l = logMetrics(metrics); + if (l) { + logger.debug('Adding logMetrics middleware'); + middleware.use(l); + } +}; + +addMiddleware(); diff --git a/lambdas/functions/termination-watcher/src/modules.d.ts b/lambdas/functions/termination-watcher/src/modules.d.ts new file mode 100644 index 0000000000..dd0eb932b0 --- /dev/null +++ b/lambdas/functions/termination-watcher/src/modules.d.ts @@ -0,0 +1,8 @@ +declare namespace NodeJS { + export interface ProcessEnv { + ENABLE_METRICS?: 'true' | 'false'; + ENVIRONMENT: string; + PREFIX?: string; + TAG_FILTERS?: string; + } +} diff --git a/lambdas/functions/termination-watcher/src/termination-warning.test.ts b/lambdas/functions/termination-watcher/src/termination-warning.test.ts new file mode 100644 index 0000000000..b1069598b2 --- /dev/null +++ b/lambdas/functions/termination-watcher/src/termination-warning.test.ts @@ -0,0 +1,158 @@ +import { DescribeInstancesCommand, EC2Client, Instance, Reservation } from '@aws-sdk/client-ec2'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; +import { handle } from './termination-warning'; +import { SpotInterruptionWarning, SpotTerminationDetail } from './types'; +import { createSingleMetric } from '@terraform-aws-github-runner/aws-powertools-util'; +import { MetricUnits } from '@aws-lambda-powertools/metrics'; + +jest.mock('@terraform-aws-github-runner/aws-powertools-util', () => ({ + ...jest.requireActual('@terraform-aws-github-runner/aws-powertools-util'), + // eslint-disable-next-line @typescript-eslint/no-unused-vars + createSingleMetric: jest.fn((name: string, unit: string, value: number, dimensions?: Record) => { + return { + addMetadata: jest.fn(), + }; + }), +})); + +const mockEC2Client = mockClient(EC2Client); + +const config = { createSpotWarningMetric: true, tagFilters: { 'ghr:environment': 'test' }, prefix: 'runners' }; + +const event: SpotInterruptionWarning = { + version: '0', + id: '1', + 'detail-type': 'EC2 Spot Instance Interruption Warning', + source: 'aws.ec2', + account: '123456789012', + time: '2015-11-11T21:29:54Z', + region: 'us-east-1', + resources: ['arn:aws:ec2:us-east-1b:instance/i-abcd1111'], + detail: { + 'instance-id': 'i-abcd1111', + 'instance-action': 'terminate', + }, +}; + +const instance: Instance = { + InstanceId: event.detail['instance-id'], + InstanceType: 't2.micro', + Tags: [ + { Key: 'Name', Value: 'test-instance' }, + { Key: 'ghr:environment', Value: 'test' }, + { Key: 'ghr:created_by', Value: 'niek' }, + ], + State: { Name: 'running' }, + LaunchTime: new Date('2021-01-01'), +}; + +const reservations: Reservation[] = [ + { + Instances: [instance], + }, +]; + +describe('handle termination warning', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should log and create an metric', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves({ Reservations: reservations }); + + await handle(event, config); + expect(createSingleMetric).toHaveBeenCalled(); + expect(createSingleMetric).toHaveBeenCalledWith('SpotInterruptionWarning', MetricUnits.Count, 1, { + InstanceType: instance.InstanceType ? instance.InstanceType : '_FAIL_', + Environment: instance.Tags?.find((tag) => tag.Key === 'ghr:environment')?.Value ?? '_FAIL_', + }); + }); + + it('should log details and not create a metric', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves({ Reservations: reservations }); + + await handle(event, { ...config, createSpotWarningMetric: false }); + expect(createSingleMetric).not.toHaveBeenCalled(); + }); + + it('should log and create matric for custom filters.', async () => { + const tags: Record = { 'ghr:custom': 'runners', 'ghr:created_by': 'niek' }; + mockEC2Client.on(DescribeInstancesCommand).resolves({ + Reservations: [ + { + Instances: [ + { + ...instance, + InstanceType: undefined, + LaunchTime: undefined, + InstanceId: undefined, + Tags: Object.keys(tags).map((key) => ({ Key: key, Value: tags[key] })), + }, + ], + }, + ], + }); + + await handle(event, { createSpotWarningMetric: true, tagFilters: tags, prefix: '' }); + expect(createSingleMetric).toHaveBeenCalled(); + }); + + it('should log and create matric for filter only with prefix match.', async () => { + // esnure instances contians tag with key gh:environment + const tagValue = instance.Tags?.find((tag) => tag.Key === 'ghr:environment')?.Value; + if (!tagValue) { + fail('Tag ghr:environment not found on instance, required for this test.'); + } + expect(tagValue?.length).toBeGreaterThan(2); + + mockEC2Client.on(DescribeInstancesCommand).resolves({ Reservations: reservations }); + + await handle(event, { + createSpotWarningMetric: true, + tagFilters: { 'ghr:environment': tagValue.substring(0, tagValue.length - 1) }, + prefix: '', + }); + expect(createSingleMetric).toHaveBeenCalled(); + }); + + it('should not log and not create matric for custom filters without a match.', async () => { + // esnure instances contians tag with key gh:environment + expect(instance.Tags?.find((tag) => tag.Key === 'ghr:environment')?.Value).toBeDefined(); + mockEC2Client.on(DescribeInstancesCommand).resolves({ Reservations: reservations }); + + await handle(event, { createSpotWarningMetric: true, tagFilters: { 'ghr:environment': '_INVALID_' }, prefix: '' }); + expect(createSingleMetric).not.toHaveBeenCalled(); + }); + + it('should log and create matric if filter is empty', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves({ Reservations: reservations }); + + await handle(event, { createSpotWarningMetric: true, tagFilters: {}, prefix: '' }); + expect(createSingleMetric).toHaveBeenCalled(); + }); + + it('should not create a metric if no instance is found.', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves({ + Reservations: [ + { + Instances: [], + }, + ], + }); + + await handle(event, config); + expect(createSingleMetric).not.toHaveBeenCalled(); + }); + + it('should not create a metric if filter not matched.', async () => { + mockEC2Client.on(DescribeInstancesCommand).resolves({ Reservations: reservations }); + + await handle(event, { + createSpotWarningMetric: true, + tagFilters: { 'ghr:environment': '_NO_MATCH_' }, + prefix: 'runners', + }); + expect(createSingleMetric).not.toHaveBeenCalled(); + }); +}); diff --git a/lambdas/functions/termination-watcher/src/termination-warning.ts b/lambdas/functions/termination-watcher/src/termination-warning.ts new file mode 100644 index 0000000000..8a9fad5af6 --- /dev/null +++ b/lambdas/functions/termination-watcher/src/termination-warning.ts @@ -0,0 +1,59 @@ +import { + createChildLogger, + createSingleMetric, + getTracedAWSV3Client, +} from '@terraform-aws-github-runner/aws-powertools-util'; +import { SpotInterruptionWarning, SpotTerminationDetail } from './types'; +import { DescribeInstancesCommand, EC2Client } from '@aws-sdk/client-ec2'; +import { Config } from './ConfigResolver'; +import { MetricUnits } from '@aws-lambda-powertools/metrics'; + +const logger = createChildLogger('termination-warning'); + +async function handle(event: SpotInterruptionWarning, config: Config): Promise { + logger.debug('Received spot notification warning:', { event }); + const ec2 = getTracedAWSV3Client(new EC2Client({ region: process.env.AWS_REGION })); + const instance = + (await ec2.send(new DescribeInstancesCommand({ InstanceIds: [event.detail['instance-id']] }))).Reservations?.[0] + .Instances?.[0] ?? null; + logger.debug('Received spot notification warning for:', { instance }); + + // check if all tags in config.tagFilter are present on the instance + const matchFilter = Object.keys(config.tagFilters).every((key) => { + return instance?.Tags?.find((tag) => tag.Key === key && tag.Value?.startsWith(config.tagFilters[key])); + }); + + if (matchFilter && instance) { + const instanceRunningTimeInSeconds = instance.LaunchTime + ? (new Date(event.time).getTime() - new Date(instance.LaunchTime).getTime()) / 1000 + : undefined; + logger.info('Received spot notification warning:', { + instanceId: instance.InstanceId, + instanceType: instance.InstanceType ?? 'unknown', + instanceName: instance.Tags?.find((tag) => tag.Key === 'Name')?.Value, + instanceState: instance.State?.Name, + instanceLaunchTime: instance.LaunchTime, + instanceRunningTimeInSeconds, + tags: instance.Tags, + }); + if (config.createSpotWarningMetric) { + const metric = createSingleMetric('SpotInterruptionWarning', MetricUnits.Count, 1, { + InstanceType: instance.InstanceType ? instance.InstanceType : 'unknown', + Environment: instance.Tags?.find((tag) => tag.Key === 'ghr:environment')?.Value ?? 'unknown', + }); + metric.addMetadata('InstanceId', instance.InstanceId ?? 'unknown'); + metric.addMetadata('InstanceType', instance.InstanceType ? instance.InstanceType : 'unknown'); + metric.addMetadata( + 'Environment', + instance.Tags?.find((tag) => tag.Key === 'ghr:environment')?.Value ?? 'unknown', + ); + } + } else { + logger.debug( + `Received spot termination notification warning for instance ${event.detail['instance-id']} but ` + + `details are not available or instance not matching the tag fileter (${config.tagFilters}).`, + ); + } +} + +export { handle }; diff --git a/lambdas/functions/termination-watcher/src/types.d.ts b/lambdas/functions/termination-watcher/src/types.d.ts new file mode 100644 index 0000000000..2a687ad4f1 --- /dev/null +++ b/lambdas/functions/termination-watcher/src/types.d.ts @@ -0,0 +1,9 @@ +import { EventBridgeEvent } from 'aws-lambda'; + +export interface SpotInterruptionWarning + extends EventBridgeEvent<'EC2 Spot Instance Interruption Warning', SpotTerminationDetail> {} + +interface SpotTerminationDetail { + 'instance-id': string; + 'instance-action': string; +} diff --git a/lambdas/functions/termination-watcher/tsconfig.json b/lambdas/functions/termination-watcher/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/functions/termination-watcher/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/lambdas/functions/webhook/jest.config.ts b/lambdas/functions/webhook/jest.config.ts new file mode 100644 index 0000000000..6a96a1fe17 --- /dev/null +++ b/lambdas/functions/webhook/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 99.13, + branches: 96.87, + functions: 100, + lines: 99.09, + }, + }, +}; + +export default config; diff --git a/lambdas/functions/webhook/package.json b/lambdas/functions/webhook/package.json new file mode 100644 index 0000000000..869400ba6c --- /dev/null +++ b/lambdas/functions/webhook/package.json @@ -0,0 +1,62 @@ +{ + "name": "@terraform-aws-github-runner/webhook", + "version": "1.0.0", + "main": "lambda.ts", + "license": "MIT", + "scripts": { + "start": "ts-node-dev src/local.ts", + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "watch": "ts-node-dev --respawn --exit-child src/local.ts", + "build": "ncc build src/lambda.ts -o dist", + "dist": "yarn build && cd dist && zip ../webhook.zip index.js", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@octokit/webhooks-definitions": "^3.67.3", + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/express": "^4.17.21", + "@types/jest": "^29.5.12", + "@types/node": "^20.8.9", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "0.38.1", + "body-parser": "^1.20.2", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "express": "^4.19.2", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "nock": "^13.4.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node-dev": "^2.0.0", + "typescript": "^5.4.5" + }, + "dependencies": { + "@aws-sdk/client-sqs": "^3.600.0", + "@middy/core": "^4.7.0", + "@octokit/rest": "^20.0.1", + "@octokit/types": "^13.5.0", + "@octokit/webhooks": "^12.1.2", + "@terraform-aws-github-runner/aws-powertools-util": "*", + "@terraform-aws-github-runner/aws-ssm-util": "*", + "aws-lambda": "^1.0.7" + }, + "nx": { + "includedScripts": [ + "build", + "dist", + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/lambdas/functions/webhook/src/ConfigResolver.ts b/lambdas/functions/webhook/src/ConfigResolver.ts new file mode 100644 index 0000000000..9296bf0d90 --- /dev/null +++ b/lambdas/functions/webhook/src/ConfigResolver.ts @@ -0,0 +1,39 @@ +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; +import { RunnerMatcherConfig } from './sqs'; +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; + +export class Config { + repositoryAllowList: Array; + static matcherConfig: Array | undefined; + static webhookSecret: string | undefined; + workflowJobEventSecondaryQueue: string | undefined; + + constructor(repositoryAllowList: Array, workflowJobEventSecondaryQueue: string | undefined) { + this.repositoryAllowList = repositoryAllowList; + + this.workflowJobEventSecondaryQueue = workflowJobEventSecondaryQueue; + } + + static async load(): Promise { + const repositoryAllowListEnv = process.env.REPOSITORY_ALLOW_LIST ?? '[]'; + const repositoryAllowList = JSON.parse(repositoryAllowListEnv) as Array; + // load parallel config if not cached + if (!Config.matcherConfig) { + const matcherConfigPath = + process.env.PARAMETER_RUNNER_MATCHER_CONFIG_PATH ?? '/github-runner/runner-matcher-config'; + const [matcherConfigVal, webhookSecret] = await Promise.all([ + getParameter(matcherConfigPath), + getParameter(process.env.PARAMETER_GITHUB_APP_WEBHOOK_SECRET), + ]); + Config.webhookSecret = webhookSecret; + Config.matcherConfig = JSON.parse(matcherConfigVal) as Array; + logger.debug('Loaded queues config', { matcherConfig: Config.matcherConfig }); + } + const workflowJobEventSecondaryQueue = process.env.SQS_WORKFLOW_JOB_QUEUE || undefined; + return new Config(repositoryAllowList, workflowJobEventSecondaryQueue); + } + + static reset(): void { + Config.matcherConfig = undefined; + } +} diff --git a/lambdas/functions/webhook/src/ValidatonError.ts b/lambdas/functions/webhook/src/ValidatonError.ts new file mode 100644 index 0000000000..3f48540507 --- /dev/null +++ b/lambdas/functions/webhook/src/ValidatonError.ts @@ -0,0 +1,13 @@ +class ValidationError extends Error { + constructor( + public statusCode: number, + public message: string, + public error?: Error, + ) { + super(message); + this.name = 'ValidationError'; + this.stack = error ? error.stack : new Error().stack; + } +} + +export default ValidationError; diff --git a/modules/webhook/lambdas/webhook/src/lambda.test.ts b/lambdas/functions/webhook/src/lambda.test.ts similarity index 82% rename from modules/webhook/lambdas/webhook/src/lambda.test.ts rename to lambdas/functions/webhook/src/lambda.test.ts index 5cb768ac68..6d1ed5da0f 100644 --- a/modules/webhook/lambdas/webhook/src/lambda.test.ts +++ b/lambdas/functions/webhook/src/lambda.test.ts @@ -1,9 +1,11 @@ +import { logger } from '@terraform-aws-github-runner/aws-powertools-util'; import { APIGatewayEvent, Context } from 'aws-lambda'; import { mocked } from 'jest-mock'; import { githubWebhook } from './lambda'; -import { handle } from './webhook/handler'; -import { logger } from './webhook/logger'; +import { handle } from './webhook'; +import ValidationError from './ValidatonError'; +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; const event: APIGatewayEvent = { body: JSON.stringify(''), @@ -71,9 +73,14 @@ const context: Context = { }, }; -jest.mock('./webhook/handler'); +jest.mock('./webhook'); +jest.mock('@terraform-aws-github-runner/aws-ssm-util'); describe('Test scale up lambda wrapper.', () => { + beforeEach(() => { + const mockedGet = mocked(getParameter); + mockedGet.mockResolvedValue('[]'); + }); it('Happy flow, resolve.', async () => { const mock = mocked(handle); mock.mockImplementation(() => { @@ -88,14 +95,10 @@ describe('Test scale up lambda wrapper.', () => { it('An expected error, resolve.', async () => { const mock = mocked(handle); - mock.mockImplementation(() => { - return new Promise((resolve) => { - resolve({ statusCode: 400 }); - }); - }); + mock.mockRejectedValue(new ValidationError(400, 'some error')); const result = await githubWebhook(event, context); - expect(result).toEqual({ statusCode: 400 }); + expect(result).toMatchObject({ statusCode: 400 }); }); it('Errors are not thrown.', async () => { diff --git a/lambdas/functions/webhook/src/lambda.ts b/lambdas/functions/webhook/src/lambda.ts new file mode 100644 index 0000000000..4bc2e3c366 --- /dev/null +++ b/lambdas/functions/webhook/src/lambda.ts @@ -0,0 +1,50 @@ +import middy from '@middy/core'; +import { logger, setContext, captureLambdaHandler, tracer } from '@terraform-aws-github-runner/aws-powertools-util'; +import { APIGatewayEvent, Context } from 'aws-lambda'; + +import { handle } from './webhook'; +import { Config } from './ConfigResolver'; +import { IncomingHttpHeaders } from 'http'; +import ValidationError from './ValidatonError'; + +export interface Response { + statusCode: number; + body?: string; +} + +middy(githubWebhook).use(captureLambdaHandler(tracer)); + +export async function githubWebhook(event: APIGatewayEvent, context: Context): Promise { + setContext(context, 'lambda.ts'); + const config = await Config.load(); + + logger.logEventIfEnabled(event); + logger.debug('Loading config', { config }); + + let result: Response; + try { + result = await handle(headersToLowerCase(event.headers), event.body as string, config); + } catch (e) { + logger.error(`Failed to handle webhook event`, { error: e }); + if (e instanceof ValidationError) { + result = { + statusCode: e.statusCode, + body: e.message, + }; + } else { + result = { + statusCode: 500, + body: 'Check the Lambda logs for the error details.', + }; + } + } + return result; +} + +// ensure header keys lower case since github headers can contain capitals. +function headersToLowerCase(headers: IncomingHttpHeaders): IncomingHttpHeaders { + for (const key in headers) { + headers[key.toLowerCase()] = headers[key]; + } + return headers; +} diff --git a/modules/webhook/lambdas/webhook/src/local.ts b/lambdas/functions/webhook/src/local.ts similarity index 60% rename from modules/webhook/lambdas/webhook/src/local.ts rename to lambdas/functions/webhook/src/local.ts index d23393d32c..ddedb552f4 100644 --- a/modules/webhook/lambdas/webhook/src/local.ts +++ b/lambdas/functions/webhook/src/local.ts @@ -1,14 +1,16 @@ import bodyParser from 'body-parser'; import express from 'express'; -import { handle } from './webhook/handler'; +import { handle } from './webhook'; +import { Config } from './ConfigResolver'; const app = express(); +const config = Config.load(); app.use(bodyParser.json()); -app.post('/event_handler', (req, res) => { - handle(req.headers, JSON.stringify(req.body)) +app.post('/event_handler', async (req, res) => { + handle(req.headers, JSON.stringify(req.body), await config) .then((c) => res.status(c.statusCode).end()) .catch((e) => { console.log(e); diff --git a/lambdas/functions/webhook/src/sqs/index.test.ts b/lambdas/functions/webhook/src/sqs/index.test.ts new file mode 100644 index 0000000000..c5c0839b36 --- /dev/null +++ b/lambdas/functions/webhook/src/sqs/index.test.ts @@ -0,0 +1,142 @@ +import { SendMessageCommandInput } from '@aws-sdk/client-sqs'; + +import { ActionRequestMessage, GithubWorkflowEvent, sendActionRequest, sendWebhookEventToWorkflowJobQueue } from '.'; +import workflowjob_event from '../../test/resources/github_workflowjob_event.json'; +import { Config } from '../ConfigResolver'; +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; +import { mocked } from 'jest-mock'; + +const mockSQS = { + sendMessage: jest.fn(() => { + return {}; + }), +}; +jest.mock('@aws-sdk/client-sqs', () => ({ + SQS: jest.fn().mockImplementation(() => mockSQS), +})); +jest.mock('@terraform-aws-github-runner/aws-ssm-util'); + +import { SQS } from '@aws-sdk/client-sqs'; + +describe('Test sending message to SQS.', () => { + const queueUrl = 'https://sqs.eu-west-1.amazonaws.com/123456789/queued-builds'; + const message = { + eventType: 'type', + id: 0, + installationId: 0, + repositoryName: 'test', + repositoryOwner: 'owner', + queueId: queueUrl, + queueFifo: false, + }; + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('no fifo queue', async () => { + // Arrange + const no_fifo_message: ActionRequestMessage = { + ...message, + queueFifo: false, + }; + const sqsMessage: SendMessageCommandInput = { + QueueUrl: queueUrl, + MessageBody: JSON.stringify(no_fifo_message), + }; + // Act + const result = await sendActionRequest(no_fifo_message); + + // Assert + expect(mockSQS.sendMessage).toBeCalledWith(sqsMessage); + expect(result).resolves; + }); + + it('use a fifo queue', async () => { + // Arrange + const fifo_message: ActionRequestMessage = { + ...message, + queueFifo: true, + }; + const sqsMessage: SendMessageCommandInput = { + QueueUrl: queueUrl, + MessageBody: JSON.stringify(fifo_message), + }; + // Act + const result = await sendActionRequest(fifo_message); + + // Assert + expect(mockSQS.sendMessage).toBeCalledWith({ ...sqsMessage, MessageGroupId: String(message.id) }); + expect(result).resolves; + }); +}); + +describe('Test sending message to SQS.', () => { + const message: GithubWorkflowEvent = { + workflowJobEvent: JSON.parse(JSON.stringify(workflowjob_event)), + }; + const sqsMessage: SendMessageCommandInput = { + QueueUrl: 'https://sqs.eu-west-1.amazonaws.com/123456789/webhook_events_workflow_job_queue', + MessageBody: JSON.stringify(message), + }; + beforeEach(() => { + const mockedGet = mocked(getParameter); + mockedGet.mockResolvedValue('[]'); + }); + afterEach(() => { + jest.clearAllMocks(); + }); + + it('sends webhook events to workflow job queue', async () => { + // Arrange + process.env.SQS_WORKFLOW_JOB_QUEUE = sqsMessage.QueueUrl; + const config = await Config.load(); + + // Act + const result = await sendWebhookEventToWorkflowJobQueue(message, config); + + // Assert + expect(mockSQS.sendMessage).toHaveBeenCalledWith(sqsMessage); + expect(result).resolves; + }); + + it('Does not send webhook events to workflow job event copy queue when job queue is not in environment', async () => { + // Arrange + delete process.env.SQS_WORKFLOW_JOB_QUEUE; + const config = await Config.load(); + + // Act + await sendWebhookEventToWorkflowJobQueue(message, config); + + // Assert + expect(SQS).not.toHaveBeenCalled(); + }); + + // eslint-disable-next-line max-len + it('Does not send webhook events to workflow job event copy queue when job queue is set to empty string', async () => { + // Arrange + process.env.SQS_WORKFLOW_JOB_QUEUE = ''; + const config = await Config.load(); + // Act + await sendWebhookEventToWorkflowJobQueue(message, config); + + // Assert + expect(SQS).not.toHaveBeenCalled(); + }); + + it('Catch the exception when even copy queue throws exception', async () => { + // Arrange + process.env.SQS_WORKFLOW_JOB_QUEUE = sqsMessage.QueueUrl; + const config = await Config.load(); + + const mockSQS = { + sendMessage: jest.fn(() => { + throw new Error(); + }), + }; + jest.mock('aws-sdk', () => ({ + SQS: jest.fn().mockImplementation(() => mockSQS), + })); + await expect(sendWebhookEventToWorkflowJobQueue(message, config)).resolves.not.toThrow(); + }); +}); diff --git a/lambdas/functions/webhook/src/sqs/index.ts b/lambdas/functions/webhook/src/sqs/index.ts new file mode 100644 index 0000000000..03539ddbf6 --- /dev/null +++ b/lambdas/functions/webhook/src/sqs/index.ts @@ -0,0 +1,70 @@ +import { SQS, SendMessageCommandInput } from '@aws-sdk/client-sqs'; +import { WorkflowJobEvent } from '@octokit/webhooks-types'; +import { createChildLogger, getTracedAWSV3Client } from '@terraform-aws-github-runner/aws-powertools-util'; +import { Config } from '../ConfigResolver'; + +const logger = createChildLogger('sqs'); + +export interface ActionRequestMessage { + id: number; + eventType: string; + repositoryName: string; + repositoryOwner: string; + installationId: number; + queueId: string; + queueFifo: boolean; +} + +export interface MatcherConfig { + labelMatchers: string[][]; + exactMatch: boolean; +} + +export type RunnerConfig = RunnerMatcherConfig[]; + +export interface RunnerMatcherConfig { + matcherConfig: MatcherConfig; + id: string; + arn: string; + fifo: boolean; +} + +export interface GithubWorkflowEvent { + workflowJobEvent: WorkflowJobEvent; +} + +export const sendActionRequest = async (message: ActionRequestMessage): Promise => { + const sqs = getTracedAWSV3Client(new SQS({ region: process.env.AWS_REGION })); + + const sqsMessage: SendMessageCommandInput = { + QueueUrl: message.queueId, + MessageBody: JSON.stringify(message), + }; + + logger.debug(`sending message to SQS: ${JSON.stringify(sqsMessage)}`); + if (message.queueFifo) { + sqsMessage.MessageGroupId = String(message.id); + } + + await sqs.sendMessage(sqsMessage); +}; + +export async function sendWebhookEventToWorkflowJobQueue(message: GithubWorkflowEvent, config: Config): Promise { + if (!config.workflowJobEventSecondaryQueue) { + return; + } + + const sqs = new SQS({ region: process.env.AWS_REGION }); + const sqsMessage: SendMessageCommandInput = { + QueueUrl: String(config.workflowJobEventSecondaryQueue), + MessageBody: JSON.stringify(message), + }; + + logger.debug(`Sending Webhook events to the workflow job queue: ${config.workflowJobEventSecondaryQueue}`); + + try { + await sqs.sendMessage(sqsMessage); + } catch (e) { + logger.warn(`Error in sending webhook events to workflow job queue: ${(e as Error).message}`); + } +} diff --git a/lambdas/functions/webhook/src/webhook/index.test.ts b/lambdas/functions/webhook/src/webhook/index.test.ts new file mode 100644 index 0000000000..cacbde23f5 --- /dev/null +++ b/lambdas/functions/webhook/src/webhook/index.test.ts @@ -0,0 +1,618 @@ +import { Webhooks } from '@octokit/webhooks'; +import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util'; +import { mocked } from 'jest-mock'; +import nock from 'nock'; + +import checkrun_event from '../../test/resources/github_check_run_event.json'; +import workflowjob_event from '../../test/resources/github_workflowjob_event.json'; +import runnerConfig from '../../test/resources/multi_runner_configurations.json'; + +import { RunnerConfig, sendActionRequest } from '../sqs'; +import { canRunJob, handle } from '.'; +import { Config } from '../ConfigResolver'; + +jest.mock('../sqs'); +jest.mock('@terraform-aws-github-runner/aws-ssm-util'); + +const GITHUB_APP_WEBHOOK_SECRET = 'TEST_SECRET'; + +const cleanEnv = process.env; + +const webhooks = new Webhooks({ + secret: 'TEST_SECRET', +}); + +const mockSQS = { + sendMessage: jest.fn(() => { + { + return { promise: jest.fn() }; + } + }), +}; +jest.mock('aws-sdk', () => ({ + SQS: jest.fn().mockImplementation(() => mockSQS), +})); + +describe('handler', () => { + let originalError: Console['error']; + let config: Config; + + beforeEach(async () => { + process.env = { ...cleanEnv }; + + nock.disableNetConnect(); + originalError = console.error; + console.error = jest.fn(); + jest.clearAllMocks(); + jest.resetAllMocks(); + + mockSSMResponse(); + config = await Config.load(); + }); + + afterEach(() => { + console.error = originalError; + }); + + it('returns 500 if no signature available', async () => { + await expect(handle({}, '', config)).rejects.toMatchObject({ + statusCode: 500, + }); + }); + + it('returns 403 if invalid signature', async () => { + const event = JSON.stringify(workflowjob_event); + const other = JSON.stringify({ ...workflowjob_event, action: 'mutated' }); + + await expect( + handle({ 'X-Hub-Signature-256': await webhooks.sign(other), 'X-GitHub-Event': 'workflow_job' }, event, config), + ).rejects.toMatchObject({ + statusCode: 401, + }); + }); + + describe('Test for workflowjob event: ', () => { + beforeEach(async () => { + config = await createConfig(undefined, runnerConfig); + }); + + it('handles workflow job events with 256 hash signature', async () => { + const event = JSON.stringify(workflowjob_event); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toHaveBeenCalled(); + }); + + it('does not handle other events', async () => { + const event = JSON.stringify(workflowjob_event); + await expect( + handle({ 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'push' }, event, config), + ).rejects.toMatchObject({ + statusCode: 202, + }); + expect(sendActionRequest).not.toHaveBeenCalled(); + }); + + it('does not handle workflow_job events with actions other than queued (action = started)', async () => { + const event = JSON.stringify({ ...workflowjob_event, action: 'started' }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).not.toHaveBeenCalled(); + }); + + it('does not handle workflow_job events with actions other than queued (action = completed)', async () => { + const event = JSON.stringify({ ...workflowjob_event, action: 'completed' }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).not.toHaveBeenCalled(); + }); + + it('does not handle workflow_job events from unlisted repositories', async () => { + const event = JSON.stringify(workflowjob_event); + config = await createConfig(['NotCodertocat/Hello-World']); + await expect( + handle({ 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, event, config), + ).rejects.toMatchObject({ + statusCode: 403, + }); + expect(sendActionRequest).not.toHaveBeenCalled(); + }); + + it('handles workflow_job events without installation id', async () => { + const event = JSON.stringify({ ...workflowjob_event, installation: null }); + config = await createConfig(['philips-labs/terraform-aws-github-runner']); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalled(); + }); + + it('handles workflow_job events from allow listed repositories', async () => { + const event = JSON.stringify(workflowjob_event); + config = await createConfig(['philips-labs/terraform-aws-github-runner']); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalled(); + }); + + it('Check runner labels accept test job', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted', 'test']], + exactMatch: true, + }, + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted', 'test1']], + exactMatch: true, + }, + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'Test'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalled(); + }); + + it('Check runner labels accept job with mixed order.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['linux', 'TEST', 'self-hosted']], + exactMatch: true, + }, + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted', 'test1']], + exactMatch: true, + }, + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['linux', 'self-hosted', 'test'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalled(); + }); + + it('Check webhook accept jobs where not all labels are provided in job.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted', 'test', 'test2']], + exactMatch: true, + }, + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted', 'test1']], + exactMatch: true, + }, + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalled(); + }); + + it('Check webhook does not accept jobs where not all labels are supported (single matcher).', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted', 'x64', 'linux']], + exactMatch: true, + }, + }, + ]); + + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'linux', 'x64', 'on-demand'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(202); + expect(sendActionRequest).not.toBeCalled(); + }); + + it('Check webhook does not accept jobs where the job labels are spread across label matchers.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [ + ['self-hosted', 'x64', 'linux'], + ['self-hosted', 'x64', 'on-demand'], + ], + exactMatch: true, + }, + }, + ]); + + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'linux', 'x64', 'on-demand'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(202); + expect(sendActionRequest).not.toBeCalled(); + }); + + it('Check webhook does not accept jobs where not all labels are supported by the runner.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted', 'x64', 'linux', 'test']], + exactMatch: true, + }, + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted', 'x64', 'linux', 'test1']], + exactMatch: true, + }, + }, + ]); + + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'linux', 'x64', 'test', 'gpu'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(202); + expect(sendActionRequest).not.toBeCalled(); + }); + + it('Check webhook will accept jobs with a single acceptable label.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted', 'test', 'test2']], + exactMatch: true, + }, + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted', 'x64']], + exactMatch: false, + }, + }, + ]); + + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['x64'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalled(); + }); + + it('Check webhook will not accept jobs without correct label when job label check all is false.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted', 'x64', 'linux', 'test']], + exactMatch: false, + }, + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted', 'x64', 'linux', 'test1']], + exactMatch: false, + }, + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['ubuntu-latest'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(202); + expect(sendActionRequest).not.toBeCalled(); + }); + it('Check webhook will accept jobs for specific labels if workflow labels are specific', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted']], + exactMatch: false, + }, + id: 'ubuntu-queue-id', + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted']], + exactMatch: false, + }, + id: 'default-queue-id', + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'ubuntu', 'x64', 'linux'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalledWith({ + id: workflowjob_event.workflow_job.id, + repositoryName: workflowjob_event.repository.name, + repositoryOwner: workflowjob_event.repository.owner.login, + eventType: 'workflow_job', + installationId: 0, + queueId: 'ubuntu-queue-id', + queueFifo: false, + }); + }); + it('Check webhook will accept jobs for latest labels if workflow labels are not specific', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [['self-hosted']], + exactMatch: false, + }, + id: 'ubuntu-queue-id', + }, + { + ...runnerConfig[1], + matcherConfig: { + labelMatchers: [['self-hosted']], + exactMatch: false, + }, + id: 'default-queue-id', + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'linux', 'x64'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalledWith({ + id: workflowjob_event.workflow_job.id, + repositoryName: workflowjob_event.repository.name, + repositoryOwner: workflowjob_event.repository.owner.login, + eventType: 'workflow_job', + installationId: 0, + queueId: 'ubuntu-queue-id', + queueFifo: false, + }); + }); + }); + + it('Check webhook will accept jobs when matchers accepts multiple labels.', async () => { + config = await createConfig(undefined, [ + { + ...runnerConfig[0], + matcherConfig: { + labelMatchers: [ + ['self-hosted', 'arm64', 'linux', 'ubuntu-latest'], + ['self-hosted', 'arm64', 'linux', 'ubuntu-2204'], + ], + exactMatch: false, + }, + id: 'ubuntu-queue-id', + }, + ]); + const event = JSON.stringify({ + ...workflowjob_event, + workflow_job: { + ...workflowjob_event.workflow_job, + labels: ['self-hosted', 'linux', 'arm64', 'ubuntu-latest'], + }, + }); + const resp = await handle( + { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, + event, + config, + ); + expect(resp.statusCode).toBe(201); + expect(sendActionRequest).toBeCalledWith({ + id: workflowjob_event.workflow_job.id, + repositoryName: workflowjob_event.repository.name, + repositoryOwner: workflowjob_event.repository.owner.login, + eventType: 'workflow_job', + installationId: 0, + queueId: 'ubuntu-queue-id', + queueFifo: false, + }); + }); + + describe('Test for check_run is ignored.', () => { + it('handles check_run events', async () => { + const event = JSON.stringify(checkrun_event); + await expect( + handle({ 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, event, config), + ).rejects.toMatchObject({ + statusCode: 202, + }); + expect(sendActionRequest).not.toHaveBeenCalled(); + }); + }); +}); + +describe('canRunJob', () => { + it('should accept job with an exact match and identical labels.', () => { + const workflowLabels = ['self-hosted', 'linux', 'x64', 'ubuntu-latest']; + const runnerLabels = [['self-hosted', 'linux', 'x64', 'ubuntu-latest']]; + const exactMatch = true; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(true); + }); + + it('should accept job with an exact match and runner supports requested capabilites.', () => { + const workflowLabels = ['self-hosted', 'linux', 'x64']; + const runnerLabels = [['self-hosted', 'linux', 'x64', 'ubuntu-latest']]; + const exactMatch = true; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(true); + }); + + it('should NOT accept job with an exact match and runner not matching requested capabilites.', () => { + const workflowLabels = ['self-hosted', 'linux', 'x64', 'ubuntu-latest']; + const runnerLabels = [['self-hosted', 'linux', 'x64']]; + const exactMatch = true; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(false); + }); + + it('should accept job with for a non exact match. Any label that matches will accept the job.', () => { + const workflowLabels = ['self-hosted', 'linux', 'x64', 'ubuntu-latest', 'gpu']; + const runnerLabels = [['gpu']]; + const exactMatch = false; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(true); + }); + + it('should NOT accept job with for an exact match. Not all requested capabilites are supported.', () => { + const workflowLabels = ['self-hosted', 'linux', 'x64', 'ubuntu-latest', 'gpu']; + const runnerLabels = [['gpu']]; + const exactMatch = true; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(false); + }); + + it('Should not accecpt jobs not providing labels if exact match is.', () => { + const workflowLabels: string[] = []; + const runnerLabels = [['self-hosted', 'linux', 'x64']]; + const exactMatch = true; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(false); + }); + + it('Should accept jobs not providing labels and exact match is set to false.', () => { + const workflowLabels: string[] = []; + const runnerLabels = [['self-hosted', 'linux', 'x64']]; + const exactMatch = false; + expect(canRunJob(workflowLabels, runnerLabels, exactMatch)).toBe(true); + }); +}); + +async function createConfig(repositoryAllowList?: string[], runnerConfig?: RunnerConfig): Promise { + if (repositoryAllowList) { + process.env.REPOSITORY_ALLOW_LIST = JSON.stringify(repositoryAllowList); + } + Config.reset(); + mockSSMResponse(runnerConfig); + return await Config.load(); +} +function mockSSMResponse(runnerConfigInput?: RunnerConfig) { + const mockedGet = mocked(getParameter); + mockedGet.mockImplementation((parameter_name) => { + const value = + parameter_name == '/github-runner/runner-matcher-config' + ? JSON.stringify(runnerConfigInput ?? runnerConfig) + : GITHUB_APP_WEBHOOK_SECRET; + return Promise.resolve(value); + }); +} diff --git a/lambdas/functions/webhook/src/webhook/index.ts b/lambdas/functions/webhook/src/webhook/index.ts new file mode 100644 index 0000000000..92daf8fea2 --- /dev/null +++ b/lambdas/functions/webhook/src/webhook/index.ts @@ -0,0 +1,150 @@ +import { Webhooks } from '@octokit/webhooks'; +import { CheckRunEvent, WorkflowJobEvent } from '@octokit/webhooks-types'; +import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util'; +import { IncomingHttpHeaders } from 'http'; + +import { Response } from '../lambda'; +import { RunnerMatcherConfig, sendActionRequest, sendWebhookEventToWorkflowJobQueue } from '../sqs'; +import ValidationError from '../ValidatonError'; +import { Config } from '../ConfigResolver'; + +const supportedEvents = ['workflow_job']; +const logger = createChildLogger('handler'); + +export async function handle(headers: IncomingHttpHeaders, body: string, config: Config): Promise { + init(headers); + + await verifySignature(headers, body); + const { event, eventType } = readEvent(headers, body); + logger.info(`Processing Github event ${event.action} for ${event.repository.full_name}`); + + validateRepoInAllowList(event, config); + + const response = await handleWorkflowJob(event, eventType, Config.matcherConfig!); + await sendWebhookEventToWorkflowJobQueue({ workflowJobEvent: event }, config); + return response; +} + +function validateRepoInAllowList(event: WorkflowJobEvent, config: Config) { + if (config.repositoryAllowList.length > 0 && !config.repositoryAllowList.includes(event.repository.full_name)) { + logger.info(`Received event from unauthorized repository ${event.repository.full_name}`); + throw new ValidationError(403, `Received event from unauthorized repository ${event.repository.full_name}`); + } +} + +async function handleWorkflowJob( + body: WorkflowJobEvent, + githubEvent: string, + matcherConfig: Array, +): Promise { + const installationId = getInstallationId(body); + if (body.action === 'queued') { + // sort the queuesConfig by order of matcher config exact match, with all true matches lined up ahead. + matcherConfig.sort((a, b) => { + return a.matcherConfig.exactMatch === b.matcherConfig.exactMatch ? 0 : a.matcherConfig.exactMatch ? -1 : 1; + }); + for (const queue of matcherConfig) { + if (canRunJob(body.workflow_job.labels, queue.matcherConfig.labelMatchers, queue.matcherConfig.exactMatch)) { + await sendActionRequest({ + id: body.workflow_job.id, + repositoryName: body.repository.name, + repositoryOwner: body.repository.owner.login, + eventType: githubEvent, + installationId: installationId, + queueId: queue.id, + queueFifo: queue.fifo, + }); + logger.info(`Successfully queued job for ${body.repository.full_name} to the queue ${queue.id}`); + return { statusCode: 201 }; + } + } + logger.warn(`Received event contains runner labels '${body.workflow_job.labels}' that are not accepted.`); + return { + statusCode: 202, + body: `Received event contains runner labels '${body.workflow_job.labels}' that are not accepted.`, + }; + } + return { statusCode: 201 }; +} + +function getInstallationId(body: WorkflowJobEvent | CheckRunEvent) { + return body.installation?.id ?? 0; +} + +export function canRunJob( + workflowJobLabels: string[], + runnerLabelsMatchers: string[][], + workflowLabelCheckAll: boolean, +): boolean { + runnerLabelsMatchers = runnerLabelsMatchers.map((runnerLabel) => { + return runnerLabel.map((label) => label.toLowerCase()); + }); + const matchLabels = workflowLabelCheckAll + ? runnerLabelsMatchers.some((rl) => workflowJobLabels.every((wl) => rl.includes(wl.toLowerCase()))) + : runnerLabelsMatchers.some((rl) => workflowJobLabels.some((wl) => rl.includes(wl.toLowerCase()))); + const match = workflowJobLabels.length === 0 ? !matchLabels : matchLabels; + + logger.debug( + `Received workflow job event with labels: '${JSON.stringify(workflowJobLabels)}'. The event does ${ + match ? '' : 'NOT ' + }match the runner labels: '${Array.from(runnerLabelsMatchers).join(',')}'`, + ); + return match; +} + +async function verifySignature(headers: IncomingHttpHeaders, body: string): Promise { + const signature = headers['x-hub-signature-256'] as string; + const webhooks = new Webhooks({ + secret: Config.webhookSecret!, + }); + + if ( + await webhooks.verify(body, signature).catch((e) => { + logger.debug('Unable to verify signature!', { e }); + throw new ValidationError(500, 'Unable to verify signature!', e as Error); + }) + ) { + return 200; + } else { + logger.debug('Unable to verify signature!', { signature, body }); + throw new ValidationError(401, 'Unable to verify signature!'); + } +} + +function init(headers: IncomingHttpHeaders) { + for (const key in headers) { + headers[key.toLowerCase()] = headers[key]; + } + + logger.addPersistentLogAttributes({ + github: { + 'github-event': headers['x-github-event'], + 'github-delivery': headers['x-github-delivery'], + }, + }); +} + +function readEvent(headers: IncomingHttpHeaders, body: string): { event: WorkflowJobEvent; eventType: string } { + const eventType = headers['x-github-event'] as string; + + if (!supportedEvents.includes(eventType)) { + logger.warn(`Unsupported event type: ${eventType}`); + throw new ValidationError(202, `Unsupported event type: ${eventType}`); + } + + const event = JSON.parse(body) as WorkflowJobEvent; + logger.addPersistentLogAttributes({ + github: { + repository: event.repository.full_name, + action: event.action, + name: event.workflow_job.name, + status: event.workflow_job.status, + workflowJobId: event.workflow_job.id, + started_at: event.workflow_job.started_at, + completed_at: event.workflow_job.completed_at, + conclusion: event.workflow_job.conclusion, + }, + }); + + return { event, eventType }; +} diff --git a/lambdas/functions/webhook/src/webhook/modules.d.ts b/lambdas/functions/webhook/src/webhook/modules.d.ts new file mode 100644 index 0000000000..7ca0bb65e4 --- /dev/null +++ b/lambdas/functions/webhook/src/webhook/modules.d.ts @@ -0,0 +1,8 @@ +declare namespace NodeJS { + export interface ProcessEnv { + ENVIRONMENT: string; + PARAMETER_GITHUB_APP_WEBHOOK_SECRET: string; + REPOSITORY_ALLOW_LIST: string; + RUNNER_LABELS: string; + } +} diff --git a/modules/webhook/lambdas/webhook/test/resources/github_check_run_event.json b/lambdas/functions/webhook/test/resources/github_check_run_event.json similarity index 100% rename from modules/webhook/lambdas/webhook/test/resources/github_check_run_event.json rename to lambdas/functions/webhook/test/resources/github_check_run_event.json diff --git a/modules/webhook/lambdas/webhook/test/resources/github_workflowjob_event.json b/lambdas/functions/webhook/test/resources/github_workflowjob_event.json similarity index 100% rename from modules/webhook/lambdas/webhook/test/resources/github_workflowjob_event.json rename to lambdas/functions/webhook/test/resources/github_workflowjob_event.json diff --git a/lambdas/functions/webhook/test/resources/multi_runner_configurations.json b/lambdas/functions/webhook/test/resources/multi_runner_configurations.json new file mode 100644 index 0000000000..a40eefd084 --- /dev/null +++ b/lambdas/functions/webhook/test/resources/multi_runner_configurations.json @@ -0,0 +1,30 @@ +[ + { + "id": "ubuntu-queue-id", + "arn": "queueARN", + "fifo": false, + "matcherConfig": { + "labelMatchers": [[ + "self-hosted", + "linux", + "x64", + "ubuntu" + ]], + "exactMatch": true + } + }, + { + "id": "latest-queue-id", + "arn": "queueARN", + "fifo": false, + "matcherConfig": { + "labelMatchers": [[ + "self-hosted", + "linux", + "x64", + "latest" + ]], + "exactMatch": false + } + } +] diff --git a/lambdas/functions/webhook/tsconfig.json b/lambdas/functions/webhook/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/functions/webhook/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/jest.config.js b/lambdas/jest.base.config.ts similarity index 50% rename from modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/jest.config.js rename to lambdas/jest.base.config.ts index 1343754d8c..88d7e18e9a 100644 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/jest.config.js +++ b/lambdas/jest.base.config.ts @@ -1,14 +1,12 @@ -module.exports = { +import type { Config } from 'jest'; + +const defaultConfig: Config = { preset: 'ts-jest', testEnvironment: 'node', collectCoverage: true, collectCoverageFrom: ['src/**/*.{ts,js,jsx}', '!src/**/*local*.ts', '!src/**/*.d.ts'], - coverageThreshold: { - global: { - branches: 85, - functions: 78, - lines: 93, - statements: 93 - } - } + coverageReporters: ['text', 'lcov', 'html'], + verbose: true }; + +export default defaultConfig; diff --git a/lambdas/libs/aws-powertools-util/jest.config.ts b/lambdas/libs/aws-powertools-util/jest.config.ts new file mode 100644 index 0000000000..6e1368d818 --- /dev/null +++ b/lambdas/libs/aws-powertools-util/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 99, + branches: 86, + functions: 100, + lines: 99, + }, + }, +}; + +export default config; diff --git a/lambdas/libs/aws-powertools-util/package.json b/lambdas/libs/aws-powertools-util/package.json new file mode 100644 index 0000000000..14e62c6da2 --- /dev/null +++ b/lambdas/libs/aws-powertools-util/package.json @@ -0,0 +1,54 @@ +{ + "name": "@terraform-aws-github-runner/aws-powertools-util", + "version": "1.0.0", + "main": "src/index.ts", + "license": "MIT", + "scripts": { + "start": "ts-node-dev src/local.ts", + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "watch": "ts-node-dev --respawn --exit-child src/local.ts", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@octokit/webhooks-definitions": "^3.67.3", + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/express": "^4.17.21", + "@types/jest": "^29.5.12", + "@types/node": "^20.8.9", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "0.38.1", + "body-parser": "^1.20.2", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "express": "^4.19.2", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "nock": "^13.4.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node-dev": "^2.0.0", + "typescript": "^5.4.5" + }, + "dependencies": { + "@aws-lambda-powertools/logger": "^1.17.0", + "@aws-lambda-powertools/metrics": "^1.18.1", + "@aws-lambda-powertools/tracer": "^1.14.0", + "aws-lambda": "^1.0.7" + }, + "nx": { + "includedScripts": [ + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/lambdas/libs/aws-powertools-util/src/index.ts b/lambdas/libs/aws-powertools-util/src/index.ts new file mode 100644 index 0000000000..1183970abe --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/index.ts @@ -0,0 +1,3 @@ +export * from './logger'; +export * from './tracer'; +export * from './metrics'; diff --git a/lambdas/libs/aws-powertools-util/src/logger/index.ts b/lambdas/libs/aws-powertools-util/src/logger/index.ts new file mode 100644 index 0000000000..195b552a74 --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/logger/index.ts @@ -0,0 +1,54 @@ +import { Logger } from '@aws-lambda-powertools/logger'; +import { Context } from 'aws-lambda'; + +const childLoggers: Logger[] = []; + +const defaultValues = { + region: process.env.AWS_REGION, + environment: process.env.ENVIRONMENT || 'N/A', +}; + +function setContext(context: Context, module?: string) { + logger.addPersistentLogAttributes({ + 'aws-request-id': context.awsRequestId, + 'function-name': context.functionName, + module: module, + }); + + // Add the context to all child loggers + childLoggers.forEach((childLogger) => { + childLogger.addPersistentLogAttributes({ + 'aws-request-id': context.awsRequestId, + 'function-name': context.functionName, + }); + }); +} + +const logger = new Logger({ + persistentLogAttributes: { + ...defaultValues, + }, +}); + +function createChildLogger(module: string): Logger { + const childLogger = logger.createChild({ + persistentLogAttributes: { + module: module, + }, + }); + + childLoggers.push(childLogger); + return childLogger; +} + +type LogAttributes = { + [key: string]: unknown; +}; + +function addPersistentContextToChildLogger(attributes: LogAttributes) { + childLoggers.forEach((childLogger) => { + childLogger.addPersistentLogAttributes(attributes); + }); +} + +export { addPersistentContextToChildLogger, createChildLogger, logger, setContext }; diff --git a/lambdas/libs/aws-powertools-util/src/logger/logger.child.test.ts b/lambdas/libs/aws-powertools-util/src/logger/logger.child.test.ts new file mode 100644 index 0000000000..15ac0ad26f --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/logger/logger.child.test.ts @@ -0,0 +1,50 @@ +import { Context } from 'aws-lambda'; + +import { addPersistentContextToChildLogger, createChildLogger, logger, setContext } from '.'; + +const childLogger = createChildLogger('child'); +addPersistentContextToChildLogger({ child: 'child' }); + +const context: Context = { + awsRequestId: '1', + callbackWaitsForEmptyEventLoop: false, + functionName: 'unit-test', + functionVersion: '', + getRemainingTimeInMillis: () => 0, + invokedFunctionArn: '', + logGroupName: '', + logStreamName: '', + memoryLimitInMB: '', + done: () => { + return; + }, + fail: () => { + return; + }, + succeed: () => { + return; + }, +}; + +describe('A child logger.', () => { + test('should log inherit context from root and combined with own context.', () => { + expect(childLogger).not.toBe(logger); + setContext(context, 'unit-test'); + + expect(logger.getPersistentLogAttributes()).toEqual( + expect.objectContaining({ + 'aws-request-id': context.awsRequestId, + 'function-name': context.functionName, + module: 'unit-test', + }), + ); + + expect(childLogger.getPersistentLogAttributes()).toEqual( + expect.objectContaining({ + module: 'child', + 'aws-request-id': context.awsRequestId, + 'function-name': context.functionName, + }), + ); + }); +}); diff --git a/lambdas/libs/aws-powertools-util/src/logger/logger.test.ts b/lambdas/libs/aws-powertools-util/src/logger/logger.test.ts new file mode 100644 index 0000000000..e708a5e45d --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/logger/logger.test.ts @@ -0,0 +1,43 @@ +import { Context } from 'aws-lambda'; + +import { logger, setContext } from '../'; + +beforeEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); +}); + +const context: Context = { + awsRequestId: '1', + callbackWaitsForEmptyEventLoop: false, + functionName: 'unit-test', + functionVersion: '', + getRemainingTimeInMillis: () => 0, + invokedFunctionArn: '', + logGroupName: '', + logStreamName: '', + memoryLimitInMB: '', + done: () => { + return; + }, + fail: () => { + return; + }, + succeed: () => { + return; + }, +}; + +describe('A root logger.', () => { + test('Should log set context.', async () => { + setContext(context, 'unit-test'); + + expect(logger.getPersistentLogAttributes()).toEqual( + expect.objectContaining({ + 'aws-request-id': context.awsRequestId, + 'function-name': context.functionName, + module: 'unit-test', + }), + ); + }); +}); diff --git a/lambdas/libs/aws-powertools-util/src/metrics/index.ts b/lambdas/libs/aws-powertools-util/src/metrics/index.ts new file mode 100644 index 0000000000..d5fd47d531 --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/metrics/index.ts @@ -0,0 +1,23 @@ +import { Metrics } from '@aws-lambda-powertools/metrics'; +import { MetricUnits } from '@aws-lambda-powertools/metrics/lib/types'; + +export const metrics = new Metrics({ + defaultDimensions: {}, +}); + +export function createSingleMetric( + name: string, + unit: MetricUnits, + value: number, + dimensions: Record = {}, +): ReturnType { + const singleMetric = metrics.singleMetric(); + + for (const dimension in dimensions) { + if (Object.prototype.hasOwnProperty.call(dimensions, dimension)) { + singleMetric.addDimension(dimension, dimensions[dimension]); + } + } + singleMetric.addMetric(name, unit, value); + return singleMetric; +} diff --git a/lambdas/libs/aws-powertools-util/src/metrics/metrics.test.ts b/lambdas/libs/aws-powertools-util/src/metrics/metrics.test.ts new file mode 100644 index 0000000000..064b0faa4b --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/metrics/metrics.test.ts @@ -0,0 +1,22 @@ +import { MetricUnits, Metrics } from '@aws-lambda-powertools/metrics'; +import { createSingleMetric } from '../'; + +process.env.POWERTOOLS_METRICS_NAMESPACE = 'test'; + +describe('A root tracer.', () => { + beforeEach(() => { + jest.restoreAllMocks(); + }); + + it('should create a single metric without dimensions', () => { + const spy = jest.spyOn(Metrics.prototype, 'singleMetric'); + createSingleMetric('test', MetricUnits.Count, 1); + expect(spy).toHaveBeenCalled(); + }); + + test('should create a single metric', () => { + const spy = jest.spyOn(Metrics.prototype, 'singleMetric'); + createSingleMetric('test', MetricUnits.Count, 1, { test: 'test' }); + expect(spy).toHaveBeenCalled(); + }); +}); diff --git a/lambdas/libs/aws-powertools-util/src/tracer/index.ts b/lambdas/libs/aws-powertools-util/src/tracer/index.ts new file mode 100644 index 0000000000..6a5757a77e --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/tracer/index.ts @@ -0,0 +1,8 @@ +import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; + +const tracer = new Tracer(); + +function getTracedAWSV3Client(client: T): T { + return tracer.captureAWSv3Client(client); +} +export { tracer, captureLambdaHandler, getTracedAWSV3Client }; diff --git a/lambdas/libs/aws-powertools-util/src/tracer/tracer.test.ts b/lambdas/libs/aws-powertools-util/src/tracer/tracer.test.ts new file mode 100644 index 0000000000..888df18ae0 --- /dev/null +++ b/lambdas/libs/aws-powertools-util/src/tracer/tracer.test.ts @@ -0,0 +1,18 @@ +import { captureLambdaHandler, getTracedAWSV3Client, tracer } from '../'; + +describe('A root tracer.', () => { + beforeEach(() => { + jest.clearAllMocks(); + jest.resetAllMocks(); + }); + + test('Should call underlying tracer.', async () => { + jest.spyOn(tracer, 'captureAWSv3Client'); + getTracedAWSV3Client({}); + expect(tracer.captureAWSv3Client).toBeCalledTimes(1); + }); + test('Should have a working middleware', async () => { + const { before } = captureLambdaHandler(tracer); + expect(before).toBeDefined(); + }); +}); diff --git a/lambdas/libs/aws-powertools-util/tsconfig.json b/lambdas/libs/aws-powertools-util/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/libs/aws-powertools-util/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/lambdas/libs/aws-ssm-util/jest.config.ts b/lambdas/libs/aws-ssm-util/jest.config.ts new file mode 100644 index 0000000000..077707f923 --- /dev/null +++ b/lambdas/libs/aws-ssm-util/jest.config.ts @@ -0,0 +1,17 @@ +import type { Config } from 'jest'; + +import defaultConfig from '../../jest.base.config'; + +const config: Config = { + ...defaultConfig, + coverageThreshold: { + global: { + statements: 100, + branches: 100, + functions: 100, + lines: 100, + }, + }, +}; + +export default config; diff --git a/lambdas/libs/aws-ssm-util/package.json b/lambdas/libs/aws-ssm-util/package.json new file mode 100644 index 0000000000..548d71c161 --- /dev/null +++ b/lambdas/libs/aws-ssm-util/package.json @@ -0,0 +1,53 @@ +{ + "name": "@terraform-aws-github-runner/aws-ssm-util", + "version": "1.0.0", + "main": "src/index.ts", + "license": "MIT", + "scripts": { + "start": "ts-node-dev src/local.ts", + "test": "NODE_ENV=test nx test", + "test:watch": "NODE_ENV=test nx test --watch", + "lint": "yarn eslint src", + "watch": "ts-node-dev --respawn --exit-child src/local.ts", + "format": "prettier --write \"**/*.ts\"", + "format-check": "prettier --check \"**/*.ts\"", + "all": "yarn build && yarn format && yarn lint && yarn test" + }, + "devDependencies": { + "@octokit/webhooks-definitions": "^3.67.3", + "@trivago/prettier-plugin-sort-imports": "^4.2.1", + "@types/aws-lambda": "^8.10.137", + "@types/express": "^4.17.21", + "@types/jest": "^29.5.12", + "@types/node": "^20.8.9", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.9.0", + "@vercel/ncc": "0.38.1", + "body-parser": "^1.20.2", + "eslint": "^8.56.0", + "eslint-plugin-prettier": "5.1.3", + "express": "^4.19.2", + "jest": "^29.5", + "jest-mock": "^29.5.0", + "nock": "^13.4.0", + "prettier": "3.3.2", + "ts-jest": "^29.1.0", + "ts-node-dev": "^2.0.0", + "typescript": "^5.4.5" + }, + "dependencies": { + "@aws-sdk/client-ssm": "^3.603.0", + "@aws-sdk/types": "^3.433.0", + "@terraform-aws-github-runner/aws-powertools-util": "*" + }, + "nx": { + "includedScripts": [ + "format", + "format-check", + "lint", + "start", + "watch", + "all" + ] + } +} diff --git a/lambdas/libs/aws-ssm-util/src/index.test.ts b/lambdas/libs/aws-ssm-util/src/index.test.ts new file mode 100644 index 0000000000..07dbc4aa3f --- /dev/null +++ b/lambdas/libs/aws-ssm-util/src/index.test.ts @@ -0,0 +1,144 @@ +import { + GetParameterCommand, + GetParameterCommandOutput, + PutParameterCommand, + PutParameterCommandOutput, + SSMClient, +} from '@aws-sdk/client-ssm'; +import { mockClient } from 'aws-sdk-client-mock'; +import 'aws-sdk-client-mock-jest'; +import nock from 'nock'; + +import { getParameter, putParameter } from '.'; + +const mockSSMClient = mockClient(SSMClient); +const cleanEnv = process.env; + +beforeEach(() => { + jest.resetModules(); + jest.clearAllMocks(); + process.env = { ...cleanEnv }; + nock.disableNetConnect(); +}); + +describe('Test getParameter and putParameter', () => { + it('Gets parameters and returns string', async () => { + // Arrange + const parameterValue = 'test'; + const parameterName = 'testParam'; + const output: GetParameterCommandOutput = { + Parameter: { + Name: parameterName, + Type: 'SecureString', + Value: parameterValue, + }, + $metadata: { + httpStatusCode: 200, + }, + }; + + mockSSMClient.on(GetParameterCommand).resolves(output); + + // Act + const result = await getParameter(parameterName); + + // Assert + expect(result).toBe(parameterValue); + }); + + it('Puts parameters and returns error on failure', async () => { + // Arrange + const parameterValue = 'test'; + const parameterName = 'testParam'; + const output: PutParameterCommandOutput = { + $metadata: { + httpStatusCode: 401, + }, + }; + + mockSSMClient.on(PutParameterCommand).resolves(output); + + // Act + expect(putParameter(parameterName, parameterValue, true)).rejects; + }); + + it('Puts parameters and returns success', async () => { + // Arrange + const parameterValue = 'test'; + const parameterName = 'testParam'; + const output: PutParameterCommandOutput = { + $metadata: { + httpStatusCode: 200, + }, + }; + + mockSSMClient.on(PutParameterCommand).resolves(output); + + // Act + expect(putParameter(parameterName, parameterValue, true)).resolves; + }); + + it('Puts parameters as String', async () => { + // Arrange + const parameterValue = 'test'; + const parameterName = 'testParam'; + const secure = false; + const output: PutParameterCommandOutput = { + $metadata: { + httpStatusCode: 200, + }, + }; + + mockSSMClient.on(PutParameterCommand).resolves(output); + + // Act + await putParameter(parameterName, parameterValue, secure); + + expect(mockSSMClient).toHaveReceivedCommandWith(PutParameterCommand, { + Name: parameterName, + Value: parameterValue, + Type: 'String', + }); + }); + + it('Puts parameters as SecureString', async () => { + // Arrange + const parameterValue = 'test'; + const parameterName = 'testParam'; + const secure = true; + const output: PutParameterCommandOutput = { + $metadata: { + httpStatusCode: 200, + }, + }; + + mockSSMClient.on(PutParameterCommand).resolves(output); + + // Act + await putParameter(parameterName, parameterValue, secure); + + expect(mockSSMClient).toHaveReceivedCommandWith(PutParameterCommand, { + Name: parameterName, + Value: parameterValue, + Type: 'SecureString', + }); + }); + + it('Gets invalid parameters and returns string', async () => { + // Arrange + const parameterName = 'invalid'; + const output: GetParameterCommandOutput = { + $metadata: { + httpStatusCode: 200, + }, + }; + + mockSSMClient.on(GetParameterCommand).resolves(output); + + // Act + const result = await getParameter(parameterName); + + // Assert + expect(result).toBe(undefined); + }); +}); diff --git a/lambdas/libs/aws-ssm-util/src/index.ts b/lambdas/libs/aws-ssm-util/src/index.ts new file mode 100644 index 0000000000..3824926d09 --- /dev/null +++ b/lambdas/libs/aws-ssm-util/src/index.ts @@ -0,0 +1,25 @@ +import { GetParameterCommand, PutParameterCommand, SSMClient, Tag } from '@aws-sdk/client-ssm'; +import { getTracedAWSV3Client } from '@terraform-aws-github-runner/aws-powertools-util'; + +export async function getParameter(parameter_name: string): Promise { + const client = getTracedAWSV3Client(new SSMClient({ region: process.env.AWS_REGION })); + return (await client.send(new GetParameterCommand({ Name: parameter_name, WithDecryption: true }))).Parameter + ?.Value as string; +} + +export async function putParameter( + parameter_name: string, + parameter_value: string, + secure: boolean, + options: { tags?: Tag[] } = {}, +): Promise { + const client = getTracedAWSV3Client(new SSMClient({ region: process.env.AWS_REGION })); + await client.send( + new PutParameterCommand({ + Name: parameter_name, + Value: parameter_value, + Type: secure ? 'SecureString' : 'String', + Tags: options.tags, + }), + ); +} diff --git a/lambdas/libs/aws-ssm-util/tsconfig.json b/lambdas/libs/aws-ssm-util/tsconfig.json new file mode 100644 index 0000000000..f34dbbda1e --- /dev/null +++ b/lambdas/libs/aws-ssm-util/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends" : "../../tsconfig.json", + "include": [ + "src/**/*" + ] +} diff --git a/lambdas/nx.json b/lambdas/nx.json new file mode 100644 index 0000000000..286763d149 --- /dev/null +++ b/lambdas/nx.json @@ -0,0 +1,40 @@ +{ + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "affected": { + "defaultBase": "main" + }, + "workspaceLayout": { + "libsDir": "libs", + "appsDir": "functions" + }, + "plugins": [ + + { + "plugin": "@nx/jest/plugin", + "options": { + "targetName": "test" + } + }, + { + "plugin": "@nx/eslint/plugin", + "options": { + "targetName": "lint" + } + } + ], +"targetDefaults": { + "build": { + "inputs": ["{projectRoot}/src/index.ts"], + "dependsOn": ["default", "^default","^build"], + "executor": "@nx/workspace:run-commands", + "cache": true + }, + "dist":{ + "outputs": ["{projectRoot}/dist/**/*"], + "dependsOn": ["build"], + "executor": "@nx/workspace:run-commands", + "cache": true + } +} + +} diff --git a/lambdas/package.json b/lambdas/package.json new file mode 100644 index 0000000000..427a559777 --- /dev/null +++ b/lambdas/package.json @@ -0,0 +1,34 @@ +{ + "name": "lambdas", + "private": true, + "workspaces": [ + "functions/*", + "libs/*" + ], + "scripts": { + "build": "nx run-many --target=build --all", + "affected:build": "nx affected:build --parallel", + "dist": "nx run-many --target=dist --all", + "format": "nx run-many --target=format --all", + "format-check": "nx run-many --target=format-check --all", + "affected:format-check": "nx affected:format-check --parallel", + "lint": "nx run-many --target=lint --all", + "affected:lint": "nx affected:lint --parallel", + "test": "nx run-many --target=test --all", + "affected:test": "nx affected:test --parallel" + }, + "resolutions": { + "@octokit/types": "^13.0.0" + }, + "devDependencies": { + "@nx/eslint": "19.4.2", + "@nx/jest": "19.4.2", + "@nx/js": "^19.4.1", + "@swc-node/register": "~1.10.2", + "@swc/core": "~1.6.13", + "@swc/helpers": "~0.5.2", + "jest": "^29.4.1", + "nx": "19.4.0", + "prettier": "^3.2.5" + } +} diff --git a/lambdas/tsconfig.json b/lambdas/tsconfig.json new file mode 100644 index 0000000000..5cbdd11306 --- /dev/null +++ b/lambdas/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, + "outDir": "dist", + "lib": [ + "es2020" + ] /* Specify library files to be included in the compilation. */, + "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, + "strict": true /* Enable all strict type-checking options. */, + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, + "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, + "resolveJsonModule": true, + } +} diff --git a/lambdas/yarn.lock b/lambdas/yarn.lock new file mode 100644 index 0000000000..321516e301 --- /dev/null +++ b/lambdas/yarn.lock @@ -0,0 +1,7995 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-lambda-powertools/commons@^1.18.1": + version "1.18.1" + resolved "https://registry.yarnpkg.com/@aws-lambda-powertools/commons/-/commons-1.18.1.tgz#fcfdef39639105a7b2b5363e4bcade9d277f5468" + integrity sha512-gFRgQ2GJDghKvf+fXvT0kQVftgOT05W+hCa7RkfZj6HSjVAO+9DZZeJL3JK1HcsLAjWRj7W9ra0/MqB3Abf+PQ== + +"@aws-lambda-powertools/logger@^1.17.0": + version "1.18.1" + resolved "https://registry.yarnpkg.com/@aws-lambda-powertools/logger/-/logger-1.18.1.tgz#6388ddbafca6b3f65277b7a364df45f426f5c592" + integrity sha512-GsSMqaFXCSz+llSOn2CVNMoN+j/jNsS6JP2Opy9myU0tvg7PeuU3+rN24vKyibUwpxM466IzWFBSJkYdm0bqVw== + dependencies: + "@aws-lambda-powertools/commons" "^1.18.1" + lodash.merge "^4.6.2" + +"@aws-lambda-powertools/metrics@^1.18.1": + version "1.18.1" + resolved "https://registry.yarnpkg.com/@aws-lambda-powertools/metrics/-/metrics-1.18.1.tgz#2d679d87b1d712bc18c6da7c1f46e67b339fcf32" + integrity sha512-ebojjuoOlm0bOtZ6H5fyTnC5B0owVX1nNqDUPEQSejkeiiBW0m6DVzy6hFWuKmGtBtm2WNnWwTE//WtF+CD6Ug== + dependencies: + "@aws-lambda-powertools/commons" "^1.18.1" + +"@aws-lambda-powertools/tracer@^1.14.0": + version "1.18.1" + resolved "https://registry.yarnpkg.com/@aws-lambda-powertools/tracer/-/tracer-1.18.1.tgz#9a6c618abb195d0e2cc25b2cd36469f9d63317bd" + integrity sha512-bMLBtdEFNmLUR9RJvBULR6XJD0XopUhhS1mlpeQlm2BCPIN3gLbqAlJK8dMXyAw8GCpLpHaziCo2+7a/AIh7lA== + dependencies: + "@aws-lambda-powertools/commons" "^1.18.1" + aws-xray-sdk-core "^3.5.3" + +"@aws-sdk/client-ec2@^3.604.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ec2/-/client-ec2-3.609.0.tgz#3ecfdd7e2b61eceec80e282aad57b162ef8102c8" + integrity sha512-yLvx4M5ieDYtPqhP/JnB4Ax/OQLfrwbe/4+IUbjdY10Krk26l4CWTHWWA9HsUjMGC22uFOh2pczvexPPDdqfAQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.609.0" + "@aws-sdk/client-sts" "3.609.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/credential-provider-node" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-sdk-ec2" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + uuid "^9.0.1" + +"@aws-sdk/client-s3@^3.600.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.609.0.tgz#bf1b9ea83f2e648452273e8739d833ff936341cf" + integrity sha512-lh8NxL9qm8eSphEcsTGjNMArYRlga4yTZCr3d7UPCRFiV1oz3e0EIA5EnxSriYi9P5Houi5d9GSWtPOel2mAow== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.609.0" + "@aws-sdk/client-sts" "3.609.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/credential-provider-node" "3.609.0" + "@aws-sdk/middleware-bucket-endpoint" "3.609.0" + "@aws-sdk/middleware-expect-continue" "3.609.0" + "@aws-sdk/middleware-flexible-checksums" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-location-constraint" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-sdk-s3" "3.609.0" + "@aws-sdk/middleware-signing" "3.609.0" + "@aws-sdk/middleware-ssec" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/signature-v4-multi-region" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@aws-sdk/xml-builder" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/eventstream-serde-browser" "^3.0.4" + "@smithy/eventstream-serde-config-resolver" "^3.0.3" + "@smithy/eventstream-serde-node" "^3.0.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-blob-browser" "^3.1.2" + "@smithy/hash-node" "^3.0.3" + "@smithy/hash-stream-node" "^3.1.2" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/md5-js" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-stream" "^3.0.5" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + +"@aws-sdk/client-sqs@^3.600.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sqs/-/client-sqs-3.609.0.tgz#a11998256f8e3d2d5e45670ada64e6563191a6f7" + integrity sha512-0cJsOWp1AOt7MYNdpq8k0nDY5g2twXdnTcryljubIXJJMrORSd4p9YtH3X8auJaqb9vd2t/D8XhoJTNbTC/4lQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.609.0" + "@aws-sdk/client-sts" "3.609.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/credential-provider-node" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-sdk-sqs" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/md5-js" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-ssm@^3.603.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.609.0.tgz#610a34d1634cc1b120994a5f780cf1f969779c55" + integrity sha512-65pwaO0rZs1sC6YrZ3cmZp6rvkIYkjhZt1TPCB5TpMvYeIpqRgoMc9edtsHWtO1MaEjda2v1uTpimQxuJ23Z/w== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.609.0" + "@aws-sdk/client-sts" "3.609.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/credential-provider-node" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + uuid "^9.0.1" + +"@aws-sdk/client-sso-oidc@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.609.0.tgz#66b3cdf6c1ede12423046ea0d0b5889655565e1a" + integrity sha512-0bNPAyPdkWkS9EGB2A9BZDkBNrnVCBzk5lYRezoT4K3/gi9w1DTYH5tuRdwaTZdxW19U1mq7CV0YJJARKO1L9Q== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/credential-provider-node" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.609.0.tgz#2a99166694b64947ba5b7453f057772bd3bba5b8" + integrity sha512-gqXGFDkIpKHCKAbeJK4aIDt3tiwJ26Rf5Tqw9JS6BYXsdMeOB8FTzqD9R+Yc1epHd8s5L94sdqXT5PapgxFZrg== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.609.0.tgz#ac373baf1d4c02adcf6162f0a6f099607046a44c" + integrity sha512-A0B3sDKFoFlGo8RYRjDBWHXpbgirer2bZBkCIzhSPHc1vOFHt/m2NcUoE2xnBKXJFrptL1xDkvo1P+XYp/BfcQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.609.0" + "@aws-sdk/core" "3.609.0" + "@aws-sdk/credential-provider-node" "3.609.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.609.0" + "@aws-sdk/region-config-resolver" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.609.0" + "@smithy/config-resolver" "^3.0.4" + "@smithy/core" "^2.2.4" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.7" + "@smithy/util-defaults-mode-node" "^3.0.7" + "@smithy/util-endpoints" "^2.0.4" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.609.0.tgz#4c3994cd341452d1ef1a8b5e81a16442a7422287" + integrity sha512-ptqw+DTxLr01+pKjDUuo53SEDzI+7nFM3WfQaEo0yhDg8vWw8PER4sWj1Ysx67ksctnZesPUjqxd5SHbtdBxiA== + dependencies: + "@smithy/core" "^2.2.4" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + fast-xml-parser "4.2.5" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.609.0.tgz#b3f32e5a8ff8b541e151eadadfb60283aa3d835e" + integrity sha512-v69ZCWcec2iuV9vLVJMa6fAb5xwkzN4jYIT8yjo2c4Ia/j976Q+TPf35Pnz5My48Xr94EFcaBazrWedF+kwfuQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.609.0.tgz#836c042a012bf1b9ff9df9ae9e3d876bb492c82e" + integrity sha512-GQQfB9Mk4XUZwaPsk4V3w8MqleS6ApkZKVQn3vTLAKa8Y7B2Imcpe5zWbKYjDd8MPpMWjHcBGFTVlDRFP4zwSQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.0.5" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.609.0.tgz#5b569a7fb8cddd0fecb1dd6444ae0599fb27121e" + integrity sha512-hwaBfXuBTv6/eAdEsDfGcteYUW6Km7lvvubbxEdxIuJNF3vswR7RMGIXaEC37hhPkTTgd3H0TONammhwZIfkog== + dependencies: + "@aws-sdk/credential-provider-env" "3.609.0" + "@aws-sdk/credential-provider-http" "3.609.0" + "@aws-sdk/credential-provider-process" "3.609.0" + "@aws-sdk/credential-provider-sso" "3.609.0" + "@aws-sdk/credential-provider-web-identity" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.1.3" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.609.0.tgz#9abcf6c9104310cc4fba70d95f0b9029ba54dea9" + integrity sha512-4J8/JRuqfxJDGD9jTHVCBxCvYt7/Vgj2Stlhj930mrjFPO/yRw8ilAAZxBWe0JHPX3QwepCmh4ErZe53F5ysxQ== + dependencies: + "@aws-sdk/credential-provider-env" "3.609.0" + "@aws-sdk/credential-provider-http" "3.609.0" + "@aws-sdk/credential-provider-ini" "3.609.0" + "@aws-sdk/credential-provider-process" "3.609.0" + "@aws-sdk/credential-provider-sso" "3.609.0" + "@aws-sdk/credential-provider-web-identity" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.1.3" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.609.0.tgz#2bfa160eec4be8532a45061810466ee3462ce240" + integrity sha512-Ux35nGOSJKZWUIM3Ny0ROZ8cqPRUEkh+tR3X2o9ydEbFiLq3eMMyEnHJqx4EeUjLRchidlm4CCid9GxMe5/gdw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.609.0.tgz#94da403a000060700a34ee62fcf119fd4cacf167" + integrity sha512-oQPGDKMMIxjvTcm86g07RPYeC7mCNk+29dPpY15ZAPRpAF7F0tircsC3wT9fHzNaKShEyK5LuI5Kg/uxsdy+Iw== + dependencies: + "@aws-sdk/client-sso" "3.609.0" + "@aws-sdk/token-providers" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.609.0.tgz#d29222d6894347ee89c781ea090d388656df1d2a" + integrity sha512-U+PG8NhlYYF45zbr1km3ROtBMYqyyj/oK8NRp++UHHeuavgrP+4wJ4wQnlEaKvJBjevfo3+dlIBcaeQ7NYejWg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/lib-storage@^3.600.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.609.0.tgz#922beb257f6007b3648be52071ae0acaddb73dc8" + integrity sha512-572EZF6x9PtDfRbRAlBx1ZNpolA6Ol3kUmZZT6lStMTsgLiAss7lJlp35eAdPTUMIREcY9E2hEbI7imPS2506g== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/smithy-client" "^3.1.5" + buffer "5.6.0" + events "3.3.0" + stream-browserify "3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.609.0.tgz#f6f1e366c1816292d6e78866653c6e7122b7932f" + integrity sha512-QhHRfr4e7FqaMUAnOAFdQVOR3yDLw40i1IZPo+TeiKyev9LEyYEX2l6DbdaIwAztofOpAxfFNj/IJ0V/efzz/w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.609.0.tgz#89af76f115aa5fadd5a82fe4e95a64cb15150517" + integrity sha512-+zeg//mSer4JZRxOB/4mUOMUJyuYPwATnIC5moBB8P8Xe+mJaVRFy8qlCtzYNj2TycnlsBPzTK0j7P1yvDh97w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.609.0.tgz#3bcd54d64e65808f2053d5a38053625cacb5464a" + integrity sha512-TJ4WE+ehT+qcrhr7/yJCzmJJPmUoPPWIbCnFzqGxauH/dpVBCslmd1vZg3h2VnfRiaDkc6f68dqYVc29CaurhQ== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-sdk/types" "3.609.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.609.0.tgz#844302cb905e4d09b9a1ea4bfa96729833068913" + integrity sha512-iTKfo158lc4jLDfYeZmYMIBHsn8m6zX+XB6birCSNZ/rrlzAkPbGE43CNdKfvjyWdqgLMRXF+B+OcZRvqhMXPQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz#7ed82d71e5ddcd50683ef2bbde10d1cc2492057e" + integrity sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz#ed44d201f091b8bac908cbf14724c7a4d492553f" + integrity sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.609.0.tgz#b7b869aaeac021a43dbea1435eaea81e5d2460b1" + integrity sha512-6sewsYB7/o/nbUfA99Aa/LokM+a/u4Wpm/X2o0RxOsDtSB795ObebLJe2BxY5UssbGaWkn7LswyfvrdZNXNj1w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-ec2@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.609.0.tgz#9392bc7efb2885c08d3154ccc4aee2de27b41f26" + integrity sha512-4VdR5WU3f6XJ0iMvy0kLkjXU6IuXy0Nq/VtRIZPtYDjYA1pnOe7SVfsvRIXHHEclURDQ/bZeXIPePIz4RijLbQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-format-url" "3.609.0" + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.609.0.tgz#a743bd63adf786c7c6d4b9102946b67a5032d1f4" + integrity sha512-kvwjL6OJFhAGWoYaIWR7HmILjiVk6xVj6QEU6qZMA7FtGgvlKi4pLfs8Of+hQqo+2TEhUoxG/5t6WqwB8uxjsw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-sqs@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.609.0.tgz#0fd301a6f9072676eaa8f83679667e90005dc4d0" + integrity sha512-0rbOiErKuKIc9fLyjiqtjgAcUt6yBBcXVwta/q+W7WLxJbNtkTfGKfKhxPtp0+5S8EyljMpg2rITBCJzNRXjiA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-signing@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.609.0.tgz#7e5c4e70302bf87a7aa3dfde83ec1b387bf819f0" + integrity sha512-2w3dBLjQVKIajYzokO4hduq8/0hSMUYHHmIo1Kdl+MSY8uwRBt12bLL6pyreobTcRMxizvn2ph/CQ9I1ST/WGQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz#b87a8bc6133f3f6bdc6801183d0f9dad3f93cf9f" + integrity sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.609.0.tgz#eb3b7c604817be42f7ecd97988dda69a22e6011b" + integrity sha512-nbq7MXRmeXm4IDqh+sJRAxGPAq0OfGmGIwKvJcw66hLoG8CmhhVMZmIAEBDFr57S+YajGwnLLRt+eMI05MMeVA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.609.0.tgz#68fe568d1c69f35f7fa3d66f718bd5751b1debda" + integrity sha512-lMHBG8zg9GWYBc9/XVPKyuAUd7iKqfPP7z04zGta2kGNOKbUTeqmAdc1gJGku75p4kglIPlGBorOxti8DhRmKw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.609.0.tgz#c88c4a25713bd50b7b253d611e3d2473258087eb" + integrity sha512-FJs0BxVMyYOKNu7nzFI1kehfgWoYmdto5B8BSS29geUACF7jlOoeCfNZWVrnMjvAxVlSQ5O7Mr575932BnsycA== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.609.0.tgz#cfa9cdc84fefe71277c7d44b08b09f42c16c1d66" + integrity sha512-WvhW/7XSf+H7YmtiIigQxfDVZVZI7mbKikQ09YpzN7FeN3TmYib1+0tB+EE9TbICkwssjiFc71FEBEh4K9grKQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/types@3.609.0", "@aws-sdk/types@^3.222.0", "@aws-sdk/types@^3.4.1", "@aws-sdk/types@^3.433.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.609.0.tgz#06b39d799c9f197a7b43670243e8e78a3bf7d6a5" + integrity sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.568.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz#6a19a8c6bbaa520b6be1c278b2b8c17875b91527" + integrity sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.609.0.tgz#e02d3fce2f999d750828dacf9f37289a1a48f6c9" + integrity sha512-Rh+3V8dOvEeE1aQmUy904DYWtLUEJ7Vf5XBPlQ6At3pBhp+zpXbsnpZzVL33c8lW1xfj6YPwtO6gOeEsl1juCQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + "@smithy/util-endpoints" "^2.0.4" + tslib "^2.6.2" + +"@aws-sdk/util-format-url@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.609.0.tgz#f53907193bb636b52b61c81bbe6d7bd5ddc76c68" + integrity sha512-fuk29BI/oLQlJ7pfm6iJ4gkEpHdavffAALZwXh9eaY1vQ0ip0aKfRTiNudPoJjyyahnz5yJ1HkmlcDitlzsOrQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" + integrity sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz#aa15421b2e32ae8bc589dac2bd6e8969832ce588" + integrity sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.609.0.tgz#f8270517b2961cbf627e4e8fb6338ad153db44bb" + integrity sha512-DlZBwQ/HkZyf3pOWc7+wjJRk5R7x9YxHhs2szHwtv1IW30KMabjjjX0GMlGJ9LLkBHkbaaEY/w9Tkj12XRLhRg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz#eeb3d5cde000a23cfeeefe0354b6193440dc7d87" + integrity sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": + version "7.21.4" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/code-frame@^7.12.13": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/code-frame@^7.22.13": + version "7.22.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e" + integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== + dependencies: + "@babel/highlight" "^7.22.13" + chalk "^2.4.2" + +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.2": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" + integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.9" + "@babel/parser" "^7.23.9" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@7.17.7": + version "7.17.7" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz" + integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.23.0", "@babel/generator@^7.7.2": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" + integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g== + dependencies: + "@babel/types" "^7.23.0" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" + integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.6", "@babel/helper-create-class-features-plugin@^7.23.9": + version "7.23.10" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz#25d55fafbaea31fd0e723820bb6cc3df72edf7ea" + integrity sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-member-expression-to-functions" "^7.23.0" + "@babel/helper-optimise-call-expression" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" + integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz#465805b7361f461e86c680f1de21eaf88c25901b" + integrity sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" + integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== + dependencies: + "@babel/types" "^7.23.0" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-optimise-call-expression@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" + integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0": + version "7.20.2" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.3": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + +"@babel/helper-remap-async-to-generator@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" + integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-wrap-function" "^7.22.20" + +"@babel/helper-replace-supers@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" + integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-optimise-call-expression" "^7.22.5" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.16.7": + version "7.19.1" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-identifier@^7.24.5", "@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helper-wrap-function@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" + integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw== + dependencies: + "@babel/helper-function-name" "^7.22.5" + "@babel/template" "^7.22.15" + "@babel/types" "^7.22.19" + +"@babel/helpers@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" + integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== + dependencies: + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/highlight@^7.18.6": + version "7.24.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e" + integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.5" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/highlight@^7.22.13": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54" + integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.5", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + +"@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" + integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" + integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-transform-optional-chaining" "^7.23.3" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7": + version "7.23.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b" + integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-proposal-decorators@^7.22.7": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.23.9.tgz#126d947d62ee72022ec46813983c6dd861456fa3" + integrity sha512-hJhBCb0+NnTWybvWq2WpbCYDOcflSbx0t+BYP65e5R9GVnukiDTi+on5bFkk4p7QGuv190H6KfNiV9Knf/3cZA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.23.9" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-decorators" "^7.23.3" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-decorators@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.23.3.tgz#a1d351d6c25bfdcf2e16f99b039101bc0ffcb0ca" + integrity sha512-cf7Niq4/+/juY67E0PbgH0TDhLQ5J7zS8C/Q5FFx+DWyrRa9sUQdTXkjqKu8zGvuqr7vw1muKiukseihU+PJDA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-import-assertions@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" + integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-attributes@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06" + integrity sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.21.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz" + integrity sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.23.3", "@babel/plugin-syntax-typescript@^7.3.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.21.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz" + integrity sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" + integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-async-generator-functions@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz#9adaeb66fc9634a586c5df139c6240d41ed801ce" + integrity sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" + integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw== + dependencies: + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-remap-async-to-generator" "^7.22.20" + +"@babel/plugin-transform-block-scoped-functions@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" + integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-block-scoping@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" + integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-properties@^7.22.5", "@babel/plugin-transform-class-properties@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48" + integrity sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-class-static-block@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5" + integrity sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.23.8": + version "7.23.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" + integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-split-export-declaration" "^7.22.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" + integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template" "^7.22.15" + +"@babel/plugin-transform-destructuring@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" + integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dotall-regex@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" + integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-duplicate-keys@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" + integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-dynamic-import@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143" + integrity sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" + integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-export-namespace-from@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191" + integrity sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" + integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + +"@babel/plugin-transform-function-name@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" + integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== + dependencies: + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-json-strings@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d" + integrity sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" + integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-logical-assignment-operators@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5" + integrity sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" + integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-amd@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" + integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw== + dependencies: + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-modules-commonjs@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" + integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== + dependencies: + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-simple-access" "^7.22.5" + +"@babel/plugin-transform-modules-systemjs@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz#105d3ed46e4a21d257f83a2f9e2ee4203ceda6be" + integrity sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw== + dependencies: + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/plugin-transform-modules-umd@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" + integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg== + dependencies: + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" + integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.5" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-new-target@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" + integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e" + integrity sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29" + integrity sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz#2b9c2d26bf62710460bdc0d1730d4f1048361b83" + integrity sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g== + dependencies: + "@babel/compat-data" "^7.23.3" + "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.23.3" + +"@babel/plugin-transform-object-super@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" + integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-replace-supers" "^7.22.20" + +"@babel/plugin-transform-optional-catch-binding@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017" + integrity sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.23.3", "@babel/plugin-transform-optional-chaining@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" + integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" + integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-methods@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4" + integrity sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-private-property-in-object@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5" + integrity sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" + integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-regenerator@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c" + integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" + integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-runtime@^7.23.2": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.9.tgz#2c64d0680fc8e09e1dfe8fd5c646fe72abd82004" + integrity sha512-A7clW3a0aSjm3ONU9o2HAILSegJCYlEZmOhmBRReVtIpY/Z/p7yIZ+wR41Z+UipwdGuqwtID/V/dOdZXjwi9gQ== + dependencies: + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + babel-plugin-polyfill-corejs2 "^0.4.8" + babel-plugin-polyfill-corejs3 "^0.9.0" + babel-plugin-polyfill-regenerator "^0.5.5" + semver "^6.3.1" + +"@babel/plugin-transform-shorthand-properties@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" + integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-spread@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" + integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" + +"@babel/plugin-transform-sticky-regex@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" + integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-template-literals@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" + integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-typeof-symbol@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" + integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-typescript@^7.23.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz#aa36a94e5da8d94339ae3a4e22d40ed287feb34c" + integrity sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.23.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/plugin-syntax-typescript" "^7.23.3" + +"@babel/plugin-transform-unicode-escapes@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" + integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-property-regex@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad" + integrity sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-regex@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" + integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-transform-unicode-sets-regex@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e" + integrity sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.22.15" + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/preset-env@^7.23.2": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.9.tgz#beace3b7994560ed6bf78e4ae2073dff45387669" + integrity sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.23.3" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.23.3" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.7" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.23.3" + "@babel/plugin-syntax-import-attributes" "^7.23.3" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.23.3" + "@babel/plugin-transform-async-generator-functions" "^7.23.9" + "@babel/plugin-transform-async-to-generator" "^7.23.3" + "@babel/plugin-transform-block-scoped-functions" "^7.23.3" + "@babel/plugin-transform-block-scoping" "^7.23.4" + "@babel/plugin-transform-class-properties" "^7.23.3" + "@babel/plugin-transform-class-static-block" "^7.23.4" + "@babel/plugin-transform-classes" "^7.23.8" + "@babel/plugin-transform-computed-properties" "^7.23.3" + "@babel/plugin-transform-destructuring" "^7.23.3" + "@babel/plugin-transform-dotall-regex" "^7.23.3" + "@babel/plugin-transform-duplicate-keys" "^7.23.3" + "@babel/plugin-transform-dynamic-import" "^7.23.4" + "@babel/plugin-transform-exponentiation-operator" "^7.23.3" + "@babel/plugin-transform-export-namespace-from" "^7.23.4" + "@babel/plugin-transform-for-of" "^7.23.6" + "@babel/plugin-transform-function-name" "^7.23.3" + "@babel/plugin-transform-json-strings" "^7.23.4" + "@babel/plugin-transform-literals" "^7.23.3" + "@babel/plugin-transform-logical-assignment-operators" "^7.23.4" + "@babel/plugin-transform-member-expression-literals" "^7.23.3" + "@babel/plugin-transform-modules-amd" "^7.23.3" + "@babel/plugin-transform-modules-commonjs" "^7.23.3" + "@babel/plugin-transform-modules-systemjs" "^7.23.9" + "@babel/plugin-transform-modules-umd" "^7.23.3" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.23.3" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.23.4" + "@babel/plugin-transform-numeric-separator" "^7.23.4" + "@babel/plugin-transform-object-rest-spread" "^7.23.4" + "@babel/plugin-transform-object-super" "^7.23.3" + "@babel/plugin-transform-optional-catch-binding" "^7.23.4" + "@babel/plugin-transform-optional-chaining" "^7.23.4" + "@babel/plugin-transform-parameters" "^7.23.3" + "@babel/plugin-transform-private-methods" "^7.23.3" + "@babel/plugin-transform-private-property-in-object" "^7.23.4" + "@babel/plugin-transform-property-literals" "^7.23.3" + "@babel/plugin-transform-regenerator" "^7.23.3" + "@babel/plugin-transform-reserved-words" "^7.23.3" + "@babel/plugin-transform-shorthand-properties" "^7.23.3" + "@babel/plugin-transform-spread" "^7.23.3" + "@babel/plugin-transform-sticky-regex" "^7.23.3" + "@babel/plugin-transform-template-literals" "^7.23.3" + "@babel/plugin-transform-typeof-symbol" "^7.23.3" + "@babel/plugin-transform-unicode-escapes" "^7.23.3" + "@babel/plugin-transform-unicode-property-regex" "^7.23.3" + "@babel/plugin-transform-unicode-regex" "^7.23.3" + "@babel/plugin-transform-unicode-sets-regex" "^7.23.3" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.8" + babel-plugin-polyfill-corejs3 "^0.9.0" + babel-plugin-polyfill-regenerator "^0.5.5" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-typescript@^7.22.5": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz#14534b34ed5b6d435aa05f1ae1c5e7adcc01d913" + integrity sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-validator-option" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.23.3" + "@babel/plugin-transform-modules-commonjs" "^7.23.3" + "@babel/plugin-transform-typescript" "^7.23.3" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.22.6", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" + integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/parser" "^7.22.15" + "@babel/types" "^7.22.15" + +"@babel/template@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/template@^7.3.3": + version "7.20.7" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@7.23.2": + version "7.23.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8" + integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.0" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.0" + "@babel/types" "^7.23.0" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.16.0", "@babel/traverse@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@7.17.0": + version "7.17.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@babel/types@^7.0.0", "@babel/types@^7.17.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" + integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@babel/types@^7.22.19", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.4.4": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@emnapi/core@^1.1.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.2.0.tgz#7b738e5033738132bf6af0b8fae7b05249bdcbd7" + integrity sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w== + dependencies: + "@emnapi/wasi-threads" "1.0.1" + tslib "^2.4.0" + +"@emnapi/runtime@^1.1.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.2.0.tgz#71d018546c3a91f3b51106530edbc056b9f2f2e3" + integrity sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz#d7ae71fd2166b1c916c6cd2d0df2ef565a2e1a5b" + integrity sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw== + dependencies: + tslib "^2.4.0" + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== + +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.4.1", "@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.4.1", "@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@middy/core@^4.7.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@middy/core/-/core-4.7.0.tgz#37e055559d5bf05dcb7b288c44644e8ae4255900" + integrity sha512-yI++DmhDQ8+ugvY7+GrEnb2PF0M/6Wzbgu4Tf7QhOlhwKGDd4j6or+Ab7qYPWx+jnKf8F0tqlmh0gV4JLi0yHw== + +"@napi-rs/wasm-runtime@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz#d27788176f250d86e498081e3c5ff48a17606918" + integrity sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ== + dependencies: + "@emnapi/core" "^1.1.0" + "@emnapi/runtime" "^1.1.0" + "@tybys/wasm-util" "^0.9.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nrwl/devkit@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-19.4.2.tgz#f1a02319b65298aa2c260daa45d4fa62f1662eb1" + integrity sha512-uvJ2kjEUq2VAQHKgaDaumFzowagqOJJgAk9dL9mdB4ZwmDi2i3XroInp/X64phrlHRyJAcYEdRJyaaM/924KVQ== + dependencies: + "@nx/devkit" "19.4.2" + +"@nrwl/jest@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-19.4.2.tgz#c5ec6a25ae00f56df4a88c6b06f4c17a85d23c61" + integrity sha512-523Ecv0NWNex88t/xDls9dAqeA/r2gaDKXzVp03YeUf61Ue5PcdEXYLzgyPuctn6dhVPKGFb1yjaojtGOtRi7A== + dependencies: + "@nx/jest" "19.4.2" + +"@nrwl/js@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nrwl/js/-/js-19.4.2.tgz#938b9f6eb187256931dba0df30864c5fb6881612" + integrity sha512-jp1VuNEWhAIDe13rqtQPxq/aw1OF+GCBJe3RKQxElZSiphFnE8PNVqFRusEsowpPVkgt40qlnsqymEa+61eczw== + dependencies: + "@nx/js" "19.4.2" + +"@nrwl/tao@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-19.4.0.tgz#6351561a0b86559e678626cfd26472837774134e" + integrity sha512-0nfSmOM9YVNTvOCCR4OiStao96YynHBOlrDdo8zdwVbKUuppD1ZwvrCZmC0xzCcsgYcQVEAgs7G/CTuFNi7Wyg== + dependencies: + nx "19.4.0" + tslib "^2.3.0" + +"@nrwl/tao@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-19.4.2.tgz#cda5078851bdb292a3e7d2b8291a7cb9d9557962" + integrity sha512-bRCRWWqR86ckji7tK4xRl9czB2WSZG4qSGqvttQMmxCvQc+njnG/QhnoGXYueaz2xr5Z1z7RJWNEqTYEAILh5Q== + dependencies: + nx "19.4.2" + tslib "^2.3.0" + +"@nrwl/workspace@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nrwl/workspace/-/workspace-19.4.2.tgz#f48a6e5800791d7a3521f24b8cc0185763b3cabb" + integrity sha512-+u8Ok6WF0rfaR5wL/WDIZtQhclLBREHvUdnjoLYtL8RspTyqSoQuOXQXP07Ln++rwLWmTIoE2NaSNKF7K0hLRQ== + dependencies: + "@nx/workspace" "19.4.2" + +"@nx/devkit@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/devkit/-/devkit-19.4.2.tgz#667e530d1f12297376545566cd1804dd7c2e5f84" + integrity sha512-4Lp3E7TiIkdYDZCk3dlCPgeTDBIaLqqEis02kgi/vO16Jek7fHet7Irkg3zU9JcjJPuoPjUyyqEXvOv5IL31IA== + dependencies: + "@nrwl/devkit" "19.4.2" + ejs "^3.1.7" + enquirer "~2.3.6" + ignore "^5.0.4" + minimatch "9.0.3" + semver "^7.5.3" + tmp "~0.2.1" + tslib "^2.3.0" + yargs-parser "21.1.1" + +"@nx/eslint@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/eslint/-/eslint-19.4.2.tgz#fb803212cb9d6509a40322dd6eec86f69f17c198" + integrity sha512-p27Sa0BidOz2Y9z+N8clbfh4+8WTRml0Ep2EJLPVBDIMNYtWnl9RCZdqM/85nkwjaRC3aWsvIcgVbYdLSiU6hw== + dependencies: + "@nx/devkit" "19.4.2" + "@nx/js" "19.4.2" + "@nx/linter" "19.4.2" + semver "^7.5.3" + tslib "^2.3.0" + typescript "~5.4.2" + +"@nx/jest@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/jest/-/jest-19.4.2.tgz#90df90d07207e3f92ce9f5d561659b17643c6573" + integrity sha512-OXpK68K853WIQZycQv+xE7lfE4CX51CDivuThIxED+aE5yYRH3M71tqM9/qkm5Jc/9Tj3qdXzU+KpPA3HBNxFg== + dependencies: + "@jest/reporters" "^29.4.1" + "@jest/test-result" "^29.4.1" + "@nrwl/jest" "19.4.2" + "@nx/devkit" "19.4.2" + "@nx/js" "19.4.2" + "@phenomnomnominal/tsquery" "~5.0.1" + chalk "^4.1.0" + identity-obj-proxy "3.0.0" + jest-config "^29.4.1" + jest-resolve "^29.4.1" + jest-util "^29.4.1" + minimatch "9.0.3" + resolve.exports "1.1.0" + tslib "^2.3.0" + yargs-parser "21.1.1" + +"@nx/js@19.4.2", "@nx/js@^19.4.1": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/js/-/js-19.4.2.tgz#b11d99898d72d8fc64f3e1f3189387582f20b561" + integrity sha512-hY3Q+W/f9uwbaT1SFy5gkfaQebrtTu8putJrwii4o7b5LehuE6/UPwTj7DR7m6t2hYWgPcZaj5Z+HsfNolNYYg== + dependencies: + "@babel/core" "^7.23.2" + "@babel/plugin-proposal-decorators" "^7.22.7" + "@babel/plugin-transform-class-properties" "^7.22.5" + "@babel/plugin-transform-runtime" "^7.23.2" + "@babel/preset-env" "^7.23.2" + "@babel/preset-typescript" "^7.22.5" + "@babel/runtime" "^7.22.6" + "@nrwl/js" "19.4.2" + "@nx/devkit" "19.4.2" + "@nx/workspace" "19.4.2" + babel-plugin-const-enum "^1.0.1" + babel-plugin-macros "^2.8.0" + babel-plugin-transform-typescript-metadata "^0.3.1" + chalk "^4.1.0" + columnify "^1.6.0" + detect-port "^1.5.1" + fast-glob "3.2.7" + fs-extra "^11.1.0" + ignore "^5.0.4" + js-tokens "^4.0.0" + minimatch "9.0.3" + npm-package-arg "11.0.1" + npm-run-path "^4.0.1" + ora "5.3.0" + semver "^7.5.3" + source-map-support "0.5.19" + ts-node "10.9.1" + tsconfig-paths "^4.1.2" + tslib "^2.3.0" + +"@nx/linter@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/linter/-/linter-19.4.2.tgz#47f6e10054f82e77bde80ea132f594497b16ce12" + integrity sha512-kPSsZOSQVVWwkjQL/s7CyLxf/uKlO6RINGum+NrqKzgnmvQAtFosa/zZ4Mm3JNAPOdrstP8uNOuoLaFCsue4ZA== + dependencies: + "@nx/eslint" "19.4.2" + +"@nx/nx-darwin-arm64@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.4.0.tgz#54dc04e24b0c4e8eb5f5c188b02320d90b9d221c" + integrity sha512-7QY/4cdLMi9+Paw5XUBNUUiAmDUBNLq2fp0TGmQvmSmgj3gQNLREjMpkfqHxYji15Z5BqV41mc67+aCSBh0B7w== + +"@nx/nx-darwin-arm64@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.4.2.tgz#f1368cb61852648df25c32a0f4a8ff8f505ea26c" + integrity sha512-yy0ik+MYli6lg9khgb0/NJIjMr2re2fpE7hl/MhaHWZmTH9PUmzz6vWpx74O3tnz93oT/9ENXFLBagQuj9hjww== + +"@nx/nx-darwin-x64@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-x64/-/nx-darwin-x64-19.4.0.tgz#dace080877cb7c7a34b14701edb43a4948418a3d" + integrity sha512-urddRcndmMhZUeqQlc4y3iHe/fb91J+JA6zGZleV1a08XS1XeEHcnIMpDfpsadlarcq5fsItSZISCKC0hFPM2g== + +"@nx/nx-darwin-x64@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-darwin-x64/-/nx-darwin-x64-19.4.2.tgz#4e56286829013f60d417e7a711da4d872f3b3985" + integrity sha512-UEZw7qzvWyOe0B5SvvrN4I2irq8FGlf1V6ut0ajL0vDbLR2IiiF6EYiM36ewpJmx5XspjhbLxEyQJn1TUMUm4w== + +"@nx/nx-freebsd-x64@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.4.0.tgz#b203b779e71e50429a639b73c4f62965c1499ade" + integrity sha512-TvV0SISYfWSu6/fTQStFj67rTSh80NNvF4SZ4tsnde0DdVsnKmWJruySXk7XeZN2Gx8tDwDwmLnBFNLdBb5x4w== + +"@nx/nx-freebsd-x64@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.4.2.tgz#326090afce2669d6471e363ade37b2db715b134c" + integrity sha512-kAB73FAe3Ae50XnZ+DrCFjbbqHJoTF2ZJVYiHdtRfAefEqsrFltM3Py2/qeeSp1Pxtri3sp4yeEui8WGV2ArWA== + +"@nx/nx-linux-arm-gnueabihf@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.4.0.tgz#88efe396787fc93aa9bcf09997968325fda18ee3" + integrity sha512-vAOAnRe+ncSv9gSawstvla5+cOknr+ZrhtIc7kHtpmIakcczTl8TWQ/9sAgX45yHYl8wLYYUCokWogNwn9r7iA== + +"@nx/nx-linux-arm-gnueabihf@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.4.2.tgz#4514e67b49e2b5cf92ec60ea90010f603ab846d0" + integrity sha512-24cHzxYB/cxlvX8I/cYZIp88TNgCrl4srMeUzqV5bHuDKVYjA1BL/gzP/pRmsdOSq+ggAKxzXhgCG3nwStUvdw== + +"@nx/nx-linux-arm64-gnu@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.4.0.tgz#0878e38f9c9ccef30e3b7b12a9515079e88912d9" + integrity sha512-x1+BQRt45ewrOF0YTHSb0u97shGA+eP0opye8AGo0aZALnaXSlJNSCgnMgP/TtPIqtZMFUJPvGUvDJ6vWJDmDQ== + +"@nx/nx-linux-arm64-gnu@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.4.2.tgz#c63ecbb33f49f5b44a4ef48a776d53ada60797f4" + integrity sha512-6gbBak/bL4vEV2aoTFc7VaeWYF+ossJ0YOqx+hwLpv9SSt6e3yIJrqf7SiwdKq0lcoPeHq3DO06+bRzNLZxVTQ== + +"@nx/nx-linux-arm64-musl@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.4.0.tgz#dde20a3aa6096b0a882c21c8d0153d807bd5f681" + integrity sha512-0mgadMfETyVJJXmxma5hHfhR3o8NbjHmz0+ZLE7wUJSnd9rh9b/Kc6xxuXnXHrm/bNVC+UOFyc/iWv04A5Z5nw== + +"@nx/nx-linux-arm64-musl@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.4.2.tgz#a5ca27414e05226d9e84358e1011b14134485d0e" + integrity sha512-JKc3Bw84jWbOhlqXGBIH9/qz3kzTwpKfsIqtar8K8Gd5/UFJS8GLEdy0mXsnoeFrA1DuYJJ0PWxoHkAa1MYLxg== + +"@nx/nx-linux-x64-gnu@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.4.0.tgz#4af77173583729e18adb4363bfd76a07ec9ab805" + integrity sha512-7kBM0TCxO6IcwgGFCdkFPb2E+rkfpZZd97xtcQAfJi2mvzlQQtekIbM3J8uNcWveTbqDkVDJaJbpvrekloQfzw== + +"@nx/nx-linux-x64-gnu@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.4.2.tgz#d6b104664b6d9ad87bb2bdad79ea0c9ae8407e5a" + integrity sha512-hyf0cDZ3rAM8WERZ/M82v1rnf6oO1X+xwYq363Qx04SufU+Knto7xHGndLNkx2i18+UtCoEr4ZhDYrIb8ZWHww== + +"@nx/nx-linux-x64-musl@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.4.0.tgz#fd8a7a31d4528c05d6ee0e8fcd80262af98ef7ba" + integrity sha512-AwKsL3HAQVNoa0umEDKdNZEjOaq3H4QlJv3vDRNPk//jKFeswlpr3NCjK34RVCPDfzmtD07OM8DAaIys2MqeNw== + +"@nx/nx-linux-x64-musl@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.4.2.tgz#0f3a74e98e9e4e8ecdc7025c712195e5bf58867e" + integrity sha512-XbKut3RTb04FNA0diDhO/OM8DgqaWaaXhyybRocfhITxH+mPQBZPUs/NM3xeQCrzlGjwrBYxt+Y9Ep8Ftgd/MA== + +"@nx/nx-win32-arm64-msvc@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.4.0.tgz#7bd4c60934b973a17738dc9c49bafa827dc5785c" + integrity sha512-/Cj2JaK3rwZSs1N3w3bi9WvITN4QnUU2yeb/9sGZm+UzJz3qi5gifvegzVDqWS+cZ6eiaekvfDwUlp1qX4MqxA== + +"@nx/nx-win32-arm64-msvc@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.4.2.tgz#49dcd35907e4c4230e718b0bd88068a315cdf6b8" + integrity sha512-VMOQ44KlndtAKE6JaXSQqrAdHBEqbJSJP4EKrBREn8HyVyr6LAfAG3Pj93ZPMvQC47uheisBcDwitxEY/Mhs1Q== + +"@nx/nx-win32-x64-msvc@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.4.0.tgz#3848c6d9a4d5d99b25c1206ab450adc8b2e85fa6" + integrity sha512-vU7/+j+8QDSclhaPKZy0qm5W9Jjo8nXJxmgUYbrI+rF9ytfoiL/9e8j0FL9ZYoQ7DScMnEK4JrcrgdtsGLsSRA== + +"@nx/nx-win32-x64-msvc@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.4.2.tgz#123e5eed15f57d9f835ccfde3469c47fee4c7956" + integrity sha512-FOK4XVanWZYM4cLS9uAx8Xg4BpPRdo0z/jt8gVto8BwgoBPIJuytGhnTVyDNgB+nRJf8K3fz7RFcZm5jup/krg== + +"@nx/workspace@19.4.2": + version "19.4.2" + resolved "https://registry.yarnpkg.com/@nx/workspace/-/workspace-19.4.2.tgz#5eeddb92e1f7a25a6e8428ecbaeef3bad2e059ab" + integrity sha512-wPRDN9jsqNzrrOjwrhEdju2tuEn2/wHW8G3kymGtQL24SHOY3+Ja1ZfZgfRqyjxHyUysVTH/xYfszDQ6qvdlhA== + dependencies: + "@nrwl/workspace" "19.4.2" + "@nx/devkit" "19.4.2" + chalk "^4.1.0" + enquirer "~2.3.6" + nx "19.4.2" + tslib "^2.3.0" + yargs-parser "21.1.1" + +"@octokit/auth-app@6.0.3": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-6.0.3.tgz#4c0ba68e8d3b1a55c34d1e68ea0ca92ef018bb7a" + integrity sha512-9N7IlBAKEJR3tJgPSubCxIDYGXSdc+2xbkjYpk9nCyqREnH8qEMoMhiEB1WgoA9yTFp91El92XNXAi+AjuKnfw== + dependencies: + "@octokit/auth-oauth-app" "^7.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^12.0.0" + deprecation "^2.3.1" + lru-cache "^10.0.0" + universal-github-app-jwt "^1.1.2" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-app@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-7.0.0.tgz#864f58152b060132098356265eb4fb07ca1fae76" + integrity sha512-8JvJEXGoEqrbzLwt3SwIUvkDd+1wrM8up0KawvDIElB8rbxPbvWppGO0SLKAWSJ0q8ILcVq+mWck6pDcZ3a9KA== + dependencies: + "@octokit/auth-oauth-device" "^6.0.0" + "@octokit/auth-oauth-user" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/types" "^11.0.0" + "@types/btoa-lite" "^1.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-device@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-6.0.0.tgz#728143108345e07e06fd5bfec8891e838c3dce96" + integrity sha512-Zgf/LKhwWk54rJaTGYVYtbKgUty+ouil6VQeRd+pCw7Gd0ECoSWaZuHK6uDGC/HtnWHjpSWFhzxPauDoHcNRtg== + dependencies: + "@octokit/oauth-methods" "^4.0.0" + "@octokit/request" "^8.0.0" + "@octokit/types" "^11.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-oauth-user@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-4.0.0.tgz#2499f25cf64ce2911ba3f2f12de176bfbc1a3805" + integrity sha512-VOm5aIkVGHaOhIvsF/4YmSjoYDzzrKbbYkdSEO0KqHK7I8SlO3ZndSikQ1fBlNPUEH0ve2BOTxLrVvI1qBf9/Q== + dependencies: + "@octokit/auth-oauth-device" "^6.0.0" + "@octokit/oauth-methods" "^4.0.0" + "@octokit/request" "^8.0.2" + "@octokit/types" "^11.0.0" + btoa-lite "^1.0.0" + universal-user-agent "^6.0.0" + +"@octokit/auth-token@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" + integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== + +"@octokit/core@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.0.0.tgz#0fc2b6eb88437e5c1d69f756a5dcee7472d2b2dd" + integrity sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A== + dependencies: + "@octokit/auth-token" "^4.0.0" + "@octokit/graphql" "^7.0.0" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^11.0.0" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + +"@octokit/endpoint@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.0.tgz#c5ce19c74b999b85af9a8a189275c80faa3e90fd" + integrity sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ== + dependencies: + "@octokit/types" "^11.0.0" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^7.0.0": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-7.0.1.tgz#f2291620e17cdaa8115f8d0cdfc0644789ec2db2" + integrity sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w== + dependencies: + "@octokit/request" "^8.0.1" + "@octokit/types" "^11.0.0" + universal-user-agent "^6.0.0" + +"@octokit/oauth-authorization-url@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-6.0.2.tgz#cc82ca29cc5e339c9921672f39f2b3f5c8eb6ef2" + integrity sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA== + +"@octokit/oauth-methods@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-4.0.0.tgz#6e0c190e8ee95afe770a4a9a4321eb159a58c794" + integrity sha512-dqy7BZLfLbi3/8X8xPKUKZclMEK9vN3fK5WF3ortRvtplQTszFvdAGbTo71gGLO+4ZxspNiLjnqdd64Chklf7w== + dependencies: + "@octokit/oauth-authorization-url" "^6.0.2" + "@octokit/request" "^8.0.2" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^11.0.0" + btoa-lite "^1.0.0" + +"@octokit/openapi-types@^22.2.0": + version "22.2.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e" + integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== + +"@octokit/plugin-paginate-rest@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz#21fd12816c2dc158a775ed20be5abcbc61052a46" + integrity sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw== + dependencies: + "@octokit/types" "^12.0.0" + +"@octokit/plugin-request-log@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-4.0.0.tgz#260fa6970aa97bbcbd91f99f3cd812e2b285c9f1" + integrity sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA== + +"@octokit/plugin-rest-endpoint-methods@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz#040b36d6a15d4c7c534b0f44050051225f884cae" + integrity sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g== + dependencies: + "@octokit/types" "^12.0.0" + +"@octokit/request-error@^5.0.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.0.tgz#ee4138538d08c81a60be3f320cd71063064a3b30" + integrity sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q== + dependencies: + "@octokit/types" "^13.1.0" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^8.0.0", "@octokit/request@^8.0.1", "@octokit/request@^8.0.2": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-8.1.1.tgz#23b4d3f164e973f4c1a0f24f68256f1646c00620" + integrity sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ== + dependencies: + "@octokit/endpoint" "^9.0.0" + "@octokit/request-error" "^5.0.0" + "@octokit/types" "^11.1.0" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/rest@20.0.2", "@octokit/rest@^20.0.1": + version "20.0.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-20.0.2.tgz#5cc8871ba01b14604439049e5f06c74b45c99594" + integrity sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ== + dependencies: + "@octokit/core" "^5.0.0" + "@octokit/plugin-paginate-rest" "^9.0.0" + "@octokit/plugin-request-log" "^4.0.0" + "@octokit/plugin-rest-endpoint-methods" "^10.0.0" + +"@octokit/types@^11.0.0", "@octokit/types@^11.1.0", "@octokit/types@^12.0.0", "@octokit/types@^13.0.0", "@octokit/types@^13.1.0", "@octokit/types@^13.5.0": + version "13.5.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.5.0.tgz#4796e56b7b267ebc7c921dcec262b3d5bfb18883" + integrity sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ== + dependencies: + "@octokit/openapi-types" "^22.2.0" + +"@octokit/webhooks-definitions@^3.67.3": + version "3.67.3" + resolved "https://registry.npmjs.org/@octokit/webhooks-definitions/-/webhooks-definitions-3.67.3.tgz" + integrity sha512-do4Z1r2OVhuI0ihJhQ8Hg+yPWnBYEBNuFNCrvtPKoYT1w81jD7pBXgGe86lYuuNirkDHb0Nxt+zt4O5GiFJfgA== + +"@octokit/webhooks-methods@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-4.1.0.tgz#681a6c86c9b21d4ec9e29108fb053ae7512be033" + integrity sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ== + +"@octokit/webhooks-types@7.4.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks-types/-/webhooks-types-7.4.0.tgz#7ed15c75908683a34e0079c80f261fe568b87395" + integrity sha512-FE2V+QZ2UYlh+9wWd5BPLNXG+J/XUD/PPq0ovS+nCcGX4+3qVbi3jYOmCTW48hg9SBBLtInx9+o7fFt4H5iP0Q== + +"@octokit/webhooks@^12.1.2": + version "12.2.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-12.2.0.tgz#ea1ee2d9d9c5a4b7b53ff8bc64a9feb0dac94161" + integrity sha512-CyuLJ0/P7bKZ+kIYw+fnkeVdhUzNuDKgNSI7pU/m7Nod0T7kP+s4s2f0pNmG9HL8/RZN1S0ZWTDll3VTMrFLAw== + dependencies: + "@octokit/request-error" "^5.0.0" + "@octokit/webhooks-methods" "^4.1.0" + "@octokit/webhooks-types" "7.4.0" + aggregate-error "^3.1.0" + +"@oxc-resolver/binding-darwin-arm64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-1.9.3.tgz#0eeb0fe47c320f1d1bc3486f9abf1fd0ec03a3f1" + integrity sha512-h3+AC4I52aVU6jbHNxUXlJrfmwo0hk+czRmw5TEmkk0sJgpd5cmGYMDlkV1puFMDn86iXWiYkGbyeijOrHOBoA== + +"@oxc-resolver/binding-darwin-x64@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-1.9.3.tgz#b401540fcd25616ba1df525f07765d96aa0a477c" + integrity sha512-h8GmaRjM5w/kftaAbMjt+7Afyc5Pu6/s2oJxVRr/vYgSdbGBHA0vlFcHjdkAn8LKfzvWr1XPzNA462DNGlA1XQ== + +"@oxc-resolver/binding-linux-arm-gnueabihf@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.9.3.tgz#5f4f664d37b0e5e90f06fae222a971b8cec9620e" + integrity sha512-2Z8u0iaOFCS5M+9FCUACaeWqgbNKa/MvYsOnFLcNEvpNBrimPbc7lO5Wyop7Hk3NoxComShYgMgwfFmdeIMJ0w== + +"@oxc-resolver/binding-linux-arm64-gnu@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.9.3.tgz#fc4ac35793064163935ec48ff9487a4f3c3508ee" + integrity sha512-GdPExK47gkL9I3ZV3nFsqEfiYUabytPK4ksHC7zRmcVnEHmwBxgDBsR4tXRpZvsri9Yvzp9qLcPq+Y+6Il0DMg== + +"@oxc-resolver/binding-linux-arm64-musl@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.9.3.tgz#7d72708479784f9bbd2822d91fb6a47b745c5aae" + integrity sha512-FEGg3C0qlX1L2Nivi+cKBMkJ0Wtyy479zycEAuQgGWcsobuLdPPb+1ekpqLACjDqrx5H7/I+1yiDd7ZeZHdFdA== + +"@oxc-resolver/binding-linux-x64-gnu@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.9.3.tgz#b900d076aa7bf14b2361c1405632db71a2b36b4f" + integrity sha512-QyzonAWPvY/VxkMKr/GNjfkk4KEsMlcy3cqCLFvsohuyxrdePzIin3tGG+9xSjGz2hzJVVXkuH5ceHmeA8yx3Q== + +"@oxc-resolver/binding-linux-x64-musl@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-1.9.3.tgz#95c9a5d1b5da4e515e1aeff4d3da5ef661e0d36d" + integrity sha512-vJ7NW5FEwlilUDzVxnOrg2fXN2D+Mgvoq+DJ5UsQlUZW2aABi68KECaF9M932t69BZz0mlyqE1ULDPNOnO3U1g== + +"@oxc-resolver/binding-wasm32-wasi@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-1.9.3.tgz#b05ce628f8ab2f57c8baf5fd8eb3628a59b5d5f0" + integrity sha512-iA0bvBHyEfyoZgbCnPPpvSogCH3Sajiggw839b6POq43sPJD+on1si1+Ao4m/lyn2sh4R3Ic8gtN011IUrpEOw== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.4" + +"@oxc-resolver/binding-win32-arm64-msvc@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.9.3.tgz#2671239d73ccf7311f0ba3fce8d5f90fa6fc859f" + integrity sha512-5drh9NvGcbcHUD0nKy6nlP9sdLeqNopsS7AM1gDlYTBxtdw0/Fb9un3S6UEQXxKVlYXp5nJ7/kDgM5va0ztbtQ== + +"@oxc-resolver/binding-win32-x64-msvc@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.9.3.tgz#4f2f3d4cbb5aa93bd1a09a65f59967b98c9e7974" + integrity sha512-Q4ZeT7jBH+FjXe9/jnto8B0hle09KCfGBYIA7wKmSY0/cRqMWsZNjZIJbGTl8p2WD/GXOvtCsAEWKE3pq4pKNQ== + +"@phenomnomnominal/tsquery@~5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz#a2a5abc89f92c01562a32806655817516653a388" + integrity sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA== + dependencies: + esquery "^1.4.0" + +"@pkgr/utils@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" + integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw== + dependencies: + cross-spawn "^7.0.3" + fast-glob "^3.3.0" + is-glob "^4.0.3" + open "^9.1.0" + picocolors "^1.0.0" + tslib "^2.6.0" + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" + integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== + dependencies: + type-detect "4.0.8" + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2", "@sinonjs/fake-timers@^10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@sinonjs/fake-timers@^11.2.2": + version "11.2.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699" + integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@sinonjs/samsam@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" + integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== + dependencies: + "@sinonjs/commons" "^2.0.0" + lodash.get "^4.4.2" + type-detect "^4.0.8" + +"@sinonjs/text-encoding@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" + integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== + +"@smithy/abort-controller@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.1.tgz#291210611ff6afecfc198d0ca72d5771d8461d16" + integrity sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz#f1104b30030f76f9aadcbd3cdca4377bd1ba2695" + integrity sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg== + dependencies: + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz#e5d3b04e9b273ba8b7ede47461e2aa96c8aa49e0" + integrity sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.4.tgz#85fffa86cee4562f867b0a70a374057a48525d1b" + integrity sha512-VwiOk7TwXoE7NlNguV/aPq1hFH72tqkHCw8eWXbr2xHspRyyv9DLpLXhq+Ieje+NwoqXrY0xyQjPXdOE6cGcHA== + dependencies: + "@smithy/node-config-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/core@^2.2.4": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.2.4.tgz#a83d62fc685ff95ad3133d55d7e365a51526a436" + integrity sha512-qdY3LpMOUyLM/gfjjMQZui+UTNS7kBRDWlvyIhVOql5dn2J3isk9qUTBtQ1CbDH8MTugHis1zu3h4rH+Qmmh4g== + dependencies: + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-retry" "^3.0.7" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.3.tgz#43e6c2d1e3df6bb6bb28bfae6b99c5a4d93bda09" + integrity sha512-U1Yrv6hx/mRK6k8AncuI6jLUx9rn0VVSd9NPEX6pyYFBfkSkChOc/n4zUb8alHUVg83TbI4OdZVo1X0Zfj3ijA== + dependencies: + "@smithy/node-config-provider" "^3.1.3" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz#4a1c72b34400631b829241151984a1ad8c4f963c" + integrity sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.4.tgz#98d6e7ae60d297e37ee7775af2a7a8bbe574579d" + integrity sha512-Eo4anLZX6ltGJTZ5yJMc80gZPYYwBn44g0h7oFq6et+TYr5dUsTpIcDbz2evsOKIZhZ7zBoFWHtBXQ4QQeb5xA== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz#f852e096d0ad112363b4685e1d441088d1fce67a" + integrity sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.4.tgz#6301752ca51b3ebabcd2dec112f1dacd990de4c1" + integrity sha512-mjlG0OzGAYuUpdUpflfb9zyLrBGgmQmrobNT8b42ZTsGv/J03+t24uhhtVEKG/b2jFtPIHF74Bq+VUtbzEKOKg== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.4.tgz#6754de5b94bdc286d8ef1d6bcf22d80f6ab68f30" + integrity sha512-Od9dv8zh3PgOD7Vj4T3HSuox16n0VG8jJIM2gvKASL6aCtcS8CfHZDWe1Ik3ZXW6xBouU+45Q5wgoliWDZiJ0A== + dependencies: + "@smithy/eventstream-codec" "^3.1.2" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.0.tgz#425ce7686bf20176b38f8013ed7fb28302a88929" + integrity sha512-vFvDxMrc6sO5Atec8PaISckMcAwsCrRhYxwUylg97bRT2KZoumOF7qk5+6EVUtuM1IG9AJV5aqXnHln9ZdXHpg== + dependencies: + "@smithy/protocol-http" "^4.0.3" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz#90281c1f183d93686fb4f26107f1819644d68829" + integrity sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg== + dependencies: + "@smithy/chunked-blob-reader" "^3.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/hash-node@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.3.tgz#82c5cb7b0f1a29ee7319081853d2d158c07dff24" + integrity sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz#89f0290ae44b113863878e75b10c484ff48af71c" + integrity sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz#8d9fd70e3a94b565a4eba4ffbdc95238e1930528" + integrity sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz#9a95c2d46b8768946a9eec7f935feaddcffa5e7a" + integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.3.tgz#55ee40aa24075b096c39f7910590c18ff7660c98" + integrity sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.3.tgz#426a7f907cc3c0a5d81deb84e16d38303e5a9ad8" + integrity sha512-Dbz2bzexReYIQDWMr+gZhpwBetNXzbhnEMhYKA6urqmojO14CsXjnsoPYO8UL/xxcawn8ZsuVU61ElkLSltIUQ== + dependencies: + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.4.tgz#c18518b21c80887c16fb595b156c7c009b0b64ca" + integrity sha512-whUJMEPwl3ANIbXjBXZVdJNgfV2ZU8ayln7xUM47rXL2txuenI7jQ/VFFwCzy5lCmXScjp6zYtptW5Evud8e9g== + dependencies: + "@smithy/middleware-serde" "^3.0.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.7.tgz#b42d90b3ecc392fdfeda1eff9dc7a023ba11d34b" + integrity sha512-f5q7Y09G+2h5ivkSx5CHvlAT4qRR3jBFEsfXyQ9nFNiWQlr8c48blnu5cmbTQ+p1xmIO14UXzKoF8d7Tm0Gsjw== + dependencies: + "@smithy/node-config-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/service-error-classification" "^3.0.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz#74d974460f74d99f38c861e6862984543a880a66" + integrity sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz#91845c7e61e6f137fa912b623b6def719a4f6ce7" + integrity sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.3.tgz#e8e69d0df5be9d6ed3f3a84f51fd2176f09c7ab8" + integrity sha512-rxdpAZczzholz6CYZxtqDu/aKTxATD5DAUDVj7HoEulq+pDSQVWzbg0btZDlxeFfa6bb2b5tUvgdX5+k8jUqcg== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.1.1.tgz#9213d9b5139c9f9c5a1928e1574de767a979bf94" + integrity sha512-L71NLyPeP450r2J/mfu1jMc//Z1YnqJt2eSNw7uhiItaONnBLDA68J5jgxq8+MBDsYnFwNAIc7dBG1ImiWBiwg== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/protocol-http" "^4.0.3" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/property-provider@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.3.tgz#afd57ea82a3f6c79fbda95e3cb85c0ee0a79f39a" + integrity sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.0.3.tgz#acf16058504e3cce2dbe8abf94f7b544cd09d3f4" + integrity sha512-x5jmrCWwQlx+Zv4jAtc33ijJ+vqqYN+c/ZkrnpvEe/uDas7AT7A/4Rc2CdfxgWv4WFGmEqODIrrUToPN6DDkGw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz#6b0e566f885bb84938d077c69e8f8555f686af13" + integrity sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz#272a6b83f88dfcbbec8283d72a6bde850cc00091" + integrity sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^2.0.4": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.1.5.tgz#0568a977cc0db36299d8703a5d8609c1f600c005" + integrity sha512-uBDTIBBEdAQryvHdc5W8sS5YX7RQzF683XrHePVdFmAgKiMofU15FLSM0/HU03hKTnazdNRFa0YHS7+ArwoUSQ== + dependencies: + "@smithy/types" "^2.12.0" + +"@smithy/service-error-classification@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz#73484255060a094aa9372f6cd972dcaf97e3ce80" + integrity sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ== + dependencies: + "@smithy/types" "^3.3.0" + +"@smithy/shared-ini-file-loader@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.3.tgz#49a5e0e8cd98d219e7e56860586710b146d52ade" + integrity sha512-Z8Y3+08vgoDgl4HENqNnnzSISAaGrF2RoKupoC47u2wiMp+Z8P/8mDh1CL8+8ujfi2U5naNvopSBmP/BUj8b5w== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-3.1.2.tgz#63fc0d4f9a955e902138fb0a57fafc96b9d4e8bb" + integrity sha512-3BcPylEsYtD0esM4Hoyml/+s7WP2LFhcM3J2AGdcL2vx9O60TtfpDOL72gjb4lU8NeRPeKAwR77YNyyGvMbuEA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.1.5.tgz#3956f0b511c3a51f859c45eb11bfd70ae00c5fec" + integrity sha512-x9bL9Mx2CT2P1OiUlHM+ZNpbVU6TgT32f9CmTRzqIHA7M4vYrROCWEoC3o4xHNJASoGd4Opos3cXYPgh+/m4Ww== + dependencies: + "@smithy/middleware-endpoint" "^3.0.4" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.0.5" + tslib "^2.6.2" + +"@smithy/types@^2.12.0": + version "2.12.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.12.0.tgz#c44845f8ba07e5e8c88eda5aed7e6a0c462da041" + integrity sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw== + dependencies: + tslib "^2.6.2" + +"@smithy/types@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" + integrity sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.3.tgz#e8a060d9810b24b1870385fc2b02485b8a6c5955" + integrity sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A== + dependencies: + "@smithy/querystring-parser" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-base64@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" + integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz#86ec2f6256310b4845a2f064e2f571c1ca164ded" + integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz#99a291bae40d8932166907fe981d6a1f54298a6d" + integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz#559fc1c86138a89b2edaefc1e6677780c24594e3" + integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz#62c6b73b22a430e84888a8f8da4b6029dd5b8efe" + integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.7.tgz#5868ae56c9ae4a3532c175f9c0ee281a41065215" + integrity sha512-Q2txLyvQyGfmjsaDbVV7Sg8psefpFcrnlGapDzXGFRPFKRBeEg6OvFK8FljqjeHSaCZ6/UuzQExUPqBR/2qlDA== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.7.tgz#e802ca57df6b8543dc288524d3894a6c357b51fc" + integrity sha512-F4Qcj1fG6MGi2BSWCslfsMSwllws/WzYONBGtLybyY+halAcXdWhcew+mej8M5SKd5hqPYp4f7b+ABQEaeytgg== + dependencies: + "@smithy/config-resolver" "^3.0.4" + "@smithy/credential-provider-imds" "^3.1.3" + "@smithy/node-config-provider" "^3.1.3" + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.1.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.0.4.tgz#0cfb01deb42ec5cd819b54e85acb2c32e4ba4385" + integrity sha512-ZAtNf+vXAsgzgRutDDiklU09ZzZiiV/nATyqde4Um4priTmasDH+eLpp3tspL0hS2dEootyFMhu1Y6Y+tzpWBQ== + dependencies: + "@smithy/node-config-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" + integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.3.tgz#07bf9602682f5a6c55bc2f0384303f85fc68c87e" + integrity sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.3.tgz#9b2ac0dbb1c81f69812a8affa4d772bebfc0e049" + integrity sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w== + dependencies: + "@smithy/service-error-classification" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-stream@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.0.5.tgz#8ca98441e1deedfc4ec8d3fee9aa4342fdbc484f" + integrity sha512-xC3L5PKMAT/Bh8fmHNXP9sdQ4+4aKVUU3EEJ2CF/lLk7R+wtMJM+v/1B4en7jO++Wa5spGzFDBCl0QxgbUc5Ug== + dependencies: + "@smithy/fetch-http-handler" "^3.2.0" + "@smithy/node-http-handler" "^3.1.1" + "@smithy/types" "^3.3.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" + integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-3.0.0.tgz#1a6a823d47cbec1fd6933e5fc87df975286d9d6a" + integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.2.tgz#2d40c3312f3537feee763459a19acafab4c75cf3" + integrity sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@swc-node/core@^1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@swc-node/core/-/core-1.13.2.tgz#0b3b563edd2a8c951dbaeecfa1795b8cd1b29a30" + integrity sha512-skceAbeKUmEK8z1nxStJTTsbIInKqW4n4+ZCYFexy6UsHjsc7MAfR2v5QqNJr/Fl/j+yLY6UkXY2VUU63nEC/Q== + +"@swc-node/register@~1.10.2": + version "1.10.2" + resolved "https://registry.yarnpkg.com/@swc-node/register/-/register-1.10.2.tgz#2bb337cd3373be55a7e2d43ba5157a0400c0346d" + integrity sha512-8Kz5l+T7LmqbDEcl8Ye2/Bz5YUYxfmo314VmMy+4kwBEZt+V/tt0/U7hCPMAu9fBdnIdJLRWjDgH4VtmpgXvug== + dependencies: + "@swc-node/core" "^1.13.2" + "@swc-node/sourcemap-support" "^0.5.1" + colorette "^2.0.20" + debug "^4.3.5" + oxc-resolver "^1.9.2" + pirates "^4.0.6" + tslib "^2.6.3" + +"@swc-node/sourcemap-support@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@swc-node/sourcemap-support/-/sourcemap-support-0.5.1.tgz#0355540d62874891770ce1ba06838de186f098ff" + integrity sha512-JxIvIo/Hrpv0JCHSyRpetAdQ6lB27oFYhv0PKCNf1g2gUXOjpeR1exrXccRxLMuAV5WAmGFBwRnNOJqN38+qtg== + dependencies: + source-map-support "^0.5.21" + tslib "^2.6.3" + +"@swc/core-darwin-arm64@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.13.tgz#dba8f8f747ad32fdb58d5b3aec4f740354d32d1b" + integrity sha512-SOF4buAis72K22BGJ3N8y88mLNfxLNprTuJUpzikyMGrvkuBFNcxYtMhmomO0XHsgLDzOJ+hWzcgjRNzjMsUcQ== + +"@swc/core-darwin-x64@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.6.13.tgz#c120207a9ced298f7382ff711bac10f6541c1c82" + integrity sha512-AW8akFSC+tmPE6YQQvK9S2A1B8pjnXEINg+gGgw0KRUUXunvu1/OEOeC5L2Co1wAwhD7bhnaefi06Qi9AiwOag== + +"@swc/core-linux-arm-gnueabihf@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.13.tgz#7b15a1fd32c18dfaf76706632cf8d19146df0d5f" + integrity sha512-f4gxxvDXVUm2HLYXRd311mSrmbpQF2MZ4Ja6XCQz1hWAxXdhRl1gpnZ+LH/xIfGSwQChrtLLVrkxdYUCVuIjFg== + +"@swc/core-linux-arm64-gnu@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.13.tgz#066b6e3c805110edb98e5125a222e3d866bf8f68" + integrity sha512-Nf/eoW2CbG8s+9JoLtjl9FByBXyQ5cjdBsA4efO7Zw4p+YSuXDgc8HRPC+E2+ns0praDpKNZtLvDtmF2lL+2Gg== + +"@swc/core-linux-arm64-musl@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.13.tgz#43a08bc118f117e485e8a9a23d3cb51fe8b4e301" + integrity sha512-2OysYSYtdw79prJYuKIiux/Gj0iaGEbpS2QZWCIY4X9sGoETJ5iMg+lY+YCrIxdkkNYd7OhIbXdYFyGs/w5LDg== + +"@swc/core-linux-x64-gnu@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.13.tgz#0f7358c95f566db6ed8a4249a190043497f41323" + integrity sha512-PkR4CZYJNk5hcd2+tMWBpnisnmYsUzazI1O5X7VkIGFcGePTqJ/bWlfUIVVExWxvAI33PQFzLbzmN5scyIUyGQ== + +"@swc/core-linux-x64-musl@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.13.tgz#6e11994ccf858edb3e70d2e8d700a5b1907a68fb" + integrity sha512-OdsY7wryTxCKwGQcwW9jwWg3cxaHBkTTHi91+5nm7hFPpmZMz1HivJrWAMwVE7iXFw+M4l6ugB/wCvpYrUAAjA== + +"@swc/core-win32-arm64-msvc@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.13.tgz#b9744644f02eb6519b0fe09031080cbf32174fb1" + integrity sha512-ap6uNmYjwk9M/+bFEuWRNl3hq4VqgQ/Lk+ID/F5WGqczNr0L7vEf+pOsRAn0F6EV+o/nyb3ePt8rLhE/wjHpPg== + +"@swc/core-win32-ia32-msvc@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.13.tgz#047302065096883f52b90052d93f9c7e63cdc67b" + integrity sha512-IJ8KH4yIUHTnS/U1jwQmtbfQals7zWPG0a9hbEfIr4zI0yKzjd83lmtS09lm2Q24QBWOCFGEEbuZxR4tIlvfzA== + +"@swc/core-win32-x64-msvc@1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.13.tgz#efd9706c38aa7dc3515acfa823b8ffa9f4a3c1a6" + integrity sha512-f6/sx6LMuEnbuxtiSL/EkR0Y6qUHFw1XVrh6rwzKXptTipUdOY+nXpKoh+1UsBm/r7H0/5DtOdrn3q5ZHbFZjQ== + +"@swc/core@~1.6.13": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.6.13.tgz#a583f614203d2350e6bb7f7c3c9c36c0e6f2a1da" + integrity sha512-eailUYex6fkfaQTev4Oa3mwn0/e3mQU4H8y1WPuImYQESOQDtVrowwUGDSc19evpBbHpKtwM+hw8nLlhIsF+Tw== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.9" + optionalDependencies: + "@swc/core-darwin-arm64" "1.6.13" + "@swc/core-darwin-x64" "1.6.13" + "@swc/core-linux-arm-gnueabihf" "1.6.13" + "@swc/core-linux-arm64-gnu" "1.6.13" + "@swc/core-linux-arm64-musl" "1.6.13" + "@swc/core-linux-x64-gnu" "1.6.13" + "@swc/core-linux-x64-musl" "1.6.13" + "@swc/core-win32-arm64-msvc" "1.6.13" + "@swc/core-win32-ia32-msvc" "1.6.13" + "@swc/core-win32-x64-msvc" "1.6.13" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@~0.5.2": + version "0.5.11" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.11.tgz#5bab8c660a6e23c13b2d23fcd1ee44a2db1b0cb7" + integrity sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A== + dependencies: + tslib "^2.4.0" + +"@swc/types@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.9.tgz#e67cdcc2e4dd74a3cef4474b465eb398e7ae83e2" + integrity sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg== + dependencies: + "@swc/counter" "^0.1.3" + +"@trivago/prettier-plugin-sort-imports@^4.2.1": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz#725f411646b3942193a37041c84e0b2116339789" + integrity sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ== + dependencies: + "@babel/generator" "7.17.7" + "@babel/parser" "^7.20.5" + "@babel/traverse" "7.23.2" + "@babel/types" "7.17.0" + javascript-natural-sort "0.7.1" + lodash "^4.17.21" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + +"@tybys/wasm-util@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355" + integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw== + dependencies: + tslib "^2.4.0" + +"@types/aws-lambda@^8.10.137": + version "8.10.140" + resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.140.tgz#617534c437f3cb9bda3e6661c25e9a1510ae9f2d" + integrity sha512-4Dh3dk2TUcbdfHrX0Al90mNGJDvA9NBiTQPzbrjGi/dLxzKCGOYgT8YQ47jUKNFALkAJAadifq0pzyjIUlhVhg== + +"@types/babel__core@^7.1.14": + version "7.20.0" + resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz" + integrity sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.18.4" + resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.4.tgz" + integrity sha512-TLG7CsGZZmX9aDF78UuJxnNTfQyRUFU0OYIVyIblr0/wd/HvsIo8wmuB90CszeD2MtLLAE9Tt4cWvk+KVkyGIw== + dependencies: + "@babel/types" "^7.3.0" + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/btoa-lite@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@types/btoa-lite/-/btoa-lite-1.0.0.tgz" + integrity sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg== + +"@types/caseless@*": + version "0.12.2" + resolved "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz" + integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== + +"@types/cls-hooked@^4.3.3": + version "4.3.8" + resolved "https://registry.yarnpkg.com/@types/cls-hooked/-/cls-hooked-4.3.8.tgz#ece275711b34eca51b3bc3899b13add7d8aff250" + integrity sha512-tf/7H883gFA6MPlWI15EQtfNZ+oPL0gLKkOlx9UHFrun1fC/FkuyNBpTKq1B5E3T4fbvjId6WifHUdSGsMMuPg== + dependencies: + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/express-serve-static-core@^4.17.33": + version "4.17.33" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz" + integrity sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@^4.17.21": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/graceful-fs@^4.1.3": + version "4.1.6" + resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz" + integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.5.12", "@types/jest@^29.5.6": + version "29.5.12" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/jsonwebtoken@^9.0.0": + version "9.0.1" + resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz" + integrity sha512-c5ltxazpWabia/4UzhIoaDcIza4KViOQhdbjRlfcIGVnsE3c3brkz9Z+F/EeJIECOQP7W7US2hNE930cWWkPiw== + dependencies: + "@types/node" "*" + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/node@*", "@types/node@^20.8.9": + version "20.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420" + integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg== + dependencies: + undici-types "~5.26.4" + +"@types/parse-json@^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/request@^2.48.11": + version "2.48.12" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30" + integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + +"@types/serve-static@*": + version "1.15.1" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz" + integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@types/sinon@^10.0.10": + version "10.0.20" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.20.tgz#f1585debf4c0d99f9938f4111e5479fb74865146" + integrity sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.5" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2" + integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ== + +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/strip-bom@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz" + integrity sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ== + +"@types/strip-json-comments@0.0.30": + version "0.0.30" + resolved "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz" + integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== + +"@types/tough-cookie@*": + version "4.0.2" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz" + integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz#b3563927341eca15124a18c6f94215f779f5c02a" + integrity sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.16.0" + "@typescript-eslint/type-utils" "7.16.0" + "@typescript-eslint/utils" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/parser@^7.9.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.15.0.tgz#f4a536e5fc6a1c05c82c4d263a2bfad2da235c80" + integrity sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A== + dependencies: + "@typescript-eslint/scope-manager" "7.15.0" + "@typescript-eslint/types" "7.15.0" + "@typescript-eslint/typescript-estree" "7.15.0" + "@typescript-eslint/visitor-keys" "7.15.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.15.0.tgz#201b34b0720be8b1447df17b963941bf044999b2" + integrity sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw== + dependencies: + "@typescript-eslint/types" "7.15.0" + "@typescript-eslint/visitor-keys" "7.15.0" + +"@typescript-eslint/scope-manager@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz#eb0757af5720c9c53c8010d7a0355ae27e17b7e5" + integrity sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw== + dependencies: + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" + +"@typescript-eslint/type-utils@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz#ec52b1932b8fb44a15a3e20208e0bd49d0b6bd00" + integrity sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg== + dependencies: + "@typescript-eslint/typescript-estree" "7.16.0" + "@typescript-eslint/utils" "7.16.0" + debug "^4.3.4" + ts-api-utils "^1.3.0" + +"@typescript-eslint/types@7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.15.0.tgz#fb894373a6e3882cbb37671ffddce44f934f62fc" + integrity sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw== + +"@typescript-eslint/types@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.16.0.tgz#60a19d7e7a6b1caa2c06fac860829d162a036ed2" + integrity sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw== + +"@typescript-eslint/typescript-estree@7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.15.0.tgz#e323bfa3966e1485b638ce751f219fc1f31eba37" + integrity sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ== + dependencies: + "@typescript-eslint/types" "7.15.0" + "@typescript-eslint/visitor-keys" "7.15.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/typescript-estree@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz#98ac779d526fab2a781e5619c9250f3e33867c09" + integrity sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw== + dependencies: + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.16.0.tgz#b38dc0ce1778e8182e227c98d91d3418449aa17f" + integrity sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "7.16.0" + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/typescript-estree" "7.16.0" + +"@typescript-eslint/visitor-keys@7.15.0": + version "7.15.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.15.0.tgz#1da0726201a859343fe6a05742a7c1792fff5b66" + integrity sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw== + dependencies: + "@typescript-eslint/types" "7.15.0" + eslint-visitor-keys "^3.4.3" + +"@typescript-eslint/visitor-keys@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz#a1d99fa7a3787962d6e0efd436575ef840e23b06" + integrity sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg== + dependencies: + "@typescript-eslint/types" "7.16.0" + eslint-visitor-keys "^3.4.3" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +"@vercel/ncc@0.38.1", "@vercel/ncc@^0.38.1": + version "0.38.1" + resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.38.1.tgz#13f08738111e1d9e8a22fd6141f3590e54d9a60e" + integrity sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +"@yarnpkg/parsers@3.0.0-rc.46": + version "3.0.0-rc.46" + resolved "https://registry.yarnpkg.com/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz#03f8363111efc0ea670e53b0282cd3ef62de4e01" + integrity sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q== + dependencies: + js-yaml "^3.10.0" + tslib "^2.4.0" + +"@zkochan/js-yaml@0.0.7": + version "0.0.7" + resolved "https://registry.yarnpkg.com/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz#4b0cb785220d7c28ce0ec4d0804deb5d821eae89" + integrity sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ== + dependencies: + argparse "^2.0.1" + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.10.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" + integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + +acorn@^8.9.0: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +address@^1.0.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== + +aggregate-error@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@^4.1.1: + version "4.1.3" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +async-hook-jl@^1.7.6: + version "1.7.6" + resolved "https://registry.yarnpkg.com/async-hook-jl/-/async-hook-jl-1.7.6.tgz#4fd25c2f864dbaf279c610d73bf97b1b28595e68" + integrity sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg== + dependencies: + stack-chain "^1.3.7" + +async@^3.2.3: + version "3.2.4" + resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +atomic-batcher@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/atomic-batcher/-/atomic-batcher-1.0.2.tgz#d16901d10ccec59516c197b9ccd8930689b813b4" + integrity sha512-EFGCRj4kLX1dHv1cDzTk+xbjBFj1GnJDpui52YmEcxxHHEWjYyT6l51U7n6WQ28osZH4S9gSybxe56Vm7vB61Q== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +aws-lambda@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/aws-lambda/-/aws-lambda-1.0.7.tgz#c6b674df47458b5ecd43ab734899ad2e2d457013" + integrity sha512-9GNFMRrEMG5y3Jvv+V4azWvc+qNWdWLTjDdhf/zgMlz8haaaLWv0xeAIWxz9PuWUBawsVxy0zZotjCdR3Xq+2w== + dependencies: + aws-sdk "^2.814.0" + commander "^3.0.2" + js-yaml "^3.14.1" + watchpack "^2.0.0-beta.10" + +aws-sdk-client-mock-jest@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-3.1.0.tgz#fc0efeb7ac49552135a648f8a7d4b7116686ea4c" + integrity sha512-pUuHS1xwzVvHadHmzZqOAxve4/RqcV0tta1mEqTcxrBOEenfy9BzhTWYcjdqQWyA5nphT2j6NM44DeSz9lD57A== + dependencies: + expect ">28.1.3" + tslib "^2.1.0" + +aws-sdk-client-mock@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aws-sdk-client-mock/-/aws-sdk-client-mock-3.1.0.tgz#5fa55e654e256c132cd2fce24645621e5486590a" + integrity sha512-3Mx5R8DDka2TB8qtr5jDbSVJsUM6uoX5tZSReBsJS8HunVtL9PHhb+RU7b+I3/53B2fJAyoEp7dJNXndBI+6MA== + dependencies: + "@types/sinon" "^10.0.10" + sinon "^16.1.3" + tslib "^2.1.0" + +aws-sdk@^2.814.0: + version "2.1365.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1365.0.tgz" + integrity sha512-GRwHfzYufi7BhBtgyzeHvqS5yCMRC5ZCqmDU/TBMnr8IaH6sabSG2iAhVn1Kkpjv3tDnWHwDr5s8wNMTzJLPmg== + dependencies: + buffer "4.9.2" + events "1.1.1" + ieee754 "1.1.13" + jmespath "0.16.0" + querystring "0.2.0" + sax "1.2.1" + url "0.10.3" + util "^0.12.4" + uuid "8.0.0" + xml2js "0.5.0" + +aws-xray-sdk-core@^3.5.3: + version "3.9.0" + resolved "https://registry.yarnpkg.com/aws-xray-sdk-core/-/aws-xray-sdk-core-3.9.0.tgz#f42b4081113c33088d8ad29d31e4bba7e94b1eed" + integrity sha512-YKzOVse7m6PCO/Uf3y3zhkWqPo5uUIU1Iin/hvL+Lpr2gFxCbNR88pkARAW2LyjvkwlcwLvx7TEoNV3SJYa4yg== + dependencies: + "@aws-sdk/types" "^3.4.1" + "@smithy/service-error-classification" "^2.0.4" + "@types/cls-hooked" "^4.3.3" + atomic-batcher "^1.0.2" + cls-hooked "^4.2.2" + semver "^7.5.3" + +axios@^1.6.0: + version "1.6.8" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" + integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^1.6.8: + version "1.7.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-const-enum@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-const-enum/-/babel-plugin-const-enum-1.2.0.tgz#3d25524106f68f081e187829ba736b251c289861" + integrity sha512-o1m/6iyyFnp9MRsK1dHF3bneqyf3AlM2q3A/YbgQr2pCat6B6XJVDv2TXqzfY2RYUi4mak6WAksSBPlyYGx9dg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-syntax-typescript" "^7.3.3" + "@babel/traverse" "^7.16.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-macros@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== + dependencies: + "@babel/runtime" "^7.7.2" + cosmiconfig "^6.0.0" + resolve "^1.12.0" + +babel-plugin-polyfill-corejs2@^0.4.8: + version "0.4.8" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz#dbcc3c8ca758a290d47c3c6a490d59429b0d2269" + integrity sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.5.0" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz#9eea32349d94556c2ad3ab9b82ebb27d4bf04a81" + integrity sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.5.0" + core-js-compat "^3.34.0" + +babel-plugin-polyfill-regenerator@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz#8b0c8fc6434239e5d7b8a9d1f832bb2b0310f06a" + integrity sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.5.0" + +babel-plugin-transform-typescript-metadata@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-typescript-metadata/-/babel-plugin-transform-typescript-metadata-0.3.2.tgz#7a327842d8c36ffe07ee1b5276434e56c297c9b7" + integrity sha512-mWEvCQTgXQf48yDqgN7CH50waTyYBeP2Lpqx4nNWab9sxEpdXVeKgfj1qYI2/TgUPQtNFZ85i3PemRtnXVYYJg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.0.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +before-after-hook@^2.2.0: + version "2.2.3" + resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz" + integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== + +big-integer@^1.6.44: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +body-parser@1.20.2, body-parser@^1.20.2: + version "1.20.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + +bplist-parser@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" + integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== + dependencies: + big-integer "^1.6.44" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browserslist@^4.22.2, browserslist@^4.22.3: + version "4.22.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" + integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A== + dependencies: + caniuse-lite "^1.0.30001580" + electron-to-chromium "^1.4.648" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +btoa-lite@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz" + integrity sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA== + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@4.9.2: + version "4.9.2" + resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +buffer@5.6.0, buffer@^5.5.0: + version "5.6.0" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +builtins@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz" + integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ== + dependencies: + semver "^7.0.0" + +bundle-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" + integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== + dependencies: + run-applescript "^5.0.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001580: + version "1.0.30001587" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz#a0bce920155fa56a1885a69c74e1163fc34b4881" + integrity sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chokidar@^3.5.1: + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@3.1.0, cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@2.6.1, cli-spinners@^2.5.0: + version "2.6.1" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz" + integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +cls-hooked@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" + integrity sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw== + dependencies: + async-hook-jl "^1.7.6" + emitter-listener "^1.0.1" + semver "^5.4.1" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +columnify@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" + integrity sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q== + dependencies: + strip-ansi "^6.0.1" + wcwidth "^1.0.0" + +combined-stream@^1.0.6, combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +convert-source-map@^1.6.0: + version "1.9.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +core-js-compat@^3.31.0, core-js-compat@^3.34.0: + version "3.36.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190" + integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw== + dependencies: + browserslist "^4.22.3" + +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cron-parser@^4.8.1: + version "4.9.0" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.9.0.tgz#0340694af3e46a0894978c6f52a6dbb5c0f11ad5" + integrity sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q== + dependencies: + luxon "^3.2.1" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +default-browser-id@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" + integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== + dependencies: + bplist-parser "^0.2.0" + untildify "^4.0.0" + +default-browser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" + integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== + dependencies: + bundle-name "^3.0.0" + default-browser-id "^3.0.0" + execa "^7.1.1" + titleize "^3.0.0" + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-lazy-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" + integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +deprecation@^2.0.0, deprecation@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detect-port@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== + dependencies: + address "^1.0.1" + debug "4" + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diff@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dotenv-expand@~11.0.6: + version "11.0.6" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-11.0.6.tgz#f2c840fd924d7c77a94eff98f153331d876882d3" + integrity sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g== + dependencies: + dotenv "^16.4.4" + +dotenv@^16.4.4, dotenv@~16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + +duplexer@^0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + +dynamic-dedupe@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz" + integrity sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ== + dependencies: + xtend "^4.0.0" + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +ejs@^3.1.7: + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== + dependencies: + jake "^10.8.5" + +electron-to-chromium@^1.4.648: + version "1.4.668" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.668.tgz#5cfed14f3240cdc70a359a49790cb295b1f097f1" + integrity sha512-ZOBocMYCehr9W31+GpMclR+KBaDZOoAEabLdhpZ8oU1JFDwIaFY0UDbpXVEUFc0BIP2O2Qn3rkfCjQmMR4T/bQ== + +emitter-listener@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.2.tgz#56b140e8f6992375b3d7cb2cab1cc7432d9632e8" + integrity sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ== + dependencies: + shimmer "^1.2.0" + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@~2.3.6: + version "2.3.6" + resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-plugin-prettier@5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" + integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.8.6" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.56.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0, esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +events@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/events/-/events-1.1.1.tgz" + integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== + +events@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz" + integrity sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +execa@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-7.2.0.tgz#657e75ba984f42a70f38928cedc87d6f2d4fe4e9" + integrity sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.1" + human-signals "^4.3.0" + is-stream "^3.0.0" + merge-stream "^2.0.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^3.0.7" + strip-final-newline "^3.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@>28.1.3, expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +express@^4.19.2: + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.2" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.6.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" + integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +figures@3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +filelist@^1.0.1: + version "1.0.4" + resolved "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + dependencies: + minimatch "^5.0.1" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +front-matter@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-4.0.2.tgz#b14e54dc745cfd7293484f3210d15ea4edd7f4d5" + integrity sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg== + dependencies: + js-yaml "^3.13.1" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^11.1.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.3: + version "1.2.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz" + integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0, get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +harmony-reflect@^1.4.6: + version "1.6.2" + resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" + integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hasown@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" + integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== + dependencies: + function-bind "^1.1.2" + +hosted-git-info@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.1.tgz#9985fcb2700467fecf7f33a4d4874e30680b5322" + integrity sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA== + dependencies: + lru-cache "^10.0.1" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +human-signals@^4.3.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" + integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +identity-obj-proxy@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA== + dependencies: + harmony-reflect "^1.4.6" + +ieee754@1.1.13: + version "1.1.13" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +ieee754@^1.1.4: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.0.4, ignore@^5.2.0, ignore@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + +import-fresh@^3.1.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-callable@^1.1.3: + version "1.2.7" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.11.0: + version "2.12.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz" + integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ== + dependencies: + has "^1.0.3" + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-docker@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" + integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-inside-container@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" + integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== + dependencies: + is-docker "^3.0.0" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-typed-array@^1.1.10, is-typed-array@^1.1.3: + version "1.1.10" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz#7a8af094cbfff1d5bb280f62ce043695ae8dd5b8" + integrity sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jake@^10.8.5: + version "10.8.5" + resolved "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz" + integrity sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw== + dependencies: + async "^3.2.3" + chalk "^4.0.2" + filelist "^1.0.1" + minimatch "^3.0.4" + +javascript-natural-sort@0.7.1: + version "0.7.1" + resolved "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz" + integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.4.1, jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.4.1, jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock-extended@^3.0.6: + version "3.0.7" + resolved "https://registry.yarnpkg.com/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz#3d902dabad99d7831bbe5fccee85ab0371c22675" + integrity sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ== + dependencies: + ts-essentials "^10.0.0" + +jest-mock@^29.5.0, jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.4.1, jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.4.1, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.4.1, jest@^29.5: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +jmespath@0.16.0: + version "0.16.0" + resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz" + integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.14.1: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonc-parser@3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonwebtoken@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +just-extend@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947" + integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +lines-and-columns@~2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz" + integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lru-cache@^10.0.0, lru-cache@^10.0.1: + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +luxon@^3.2.1: + version "3.3.0" + resolved "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz" + integrity sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg== + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^4.0.4: + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +moment-timezone@^0.5.45: + version "0.5.45" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== + dependencies: + moment "^2.29.4" + +moment@^2.29.4: + version "2.29.4" + resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2, ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +nise@^5.1.4: + version "5.1.9" + resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.9.tgz#0cb73b5e4499d738231a473cd89bd8afbb618139" + integrity sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^11.2.2" + "@sinonjs/text-encoding" "^0.7.2" + just-extend "^6.2.0" + path-to-regexp "^6.2.1" + +nock@^13.4.0: + version "13.5.4" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.4.tgz#8918f0addc70a63736170fef7106a9721e0dc479" + integrity sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-machine-id@1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/node-machine-id/-/node-machine-id-1.1.12.tgz#37904eee1e59b320bb9c5d6c0a59f3b469cb6267" + integrity sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-package-arg@11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.1.tgz#f208b0022c29240a1c532a449bdde3f0a4708ebc" + integrity sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ== + dependencies: + hosted-git-info "^7.0.0" + proc-log "^3.0.0" + semver "^7.3.5" + validate-npm-package-name "^5.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + +nx@19.4.0: + version "19.4.0" + resolved "https://registry.yarnpkg.com/nx/-/nx-19.4.0.tgz#0e6078cf4e399a6b1a32f9f743441d2f53f16fd0" + integrity sha512-tTdKqJ7e9imww6fyx3KrLcMz7oAFIcHFeXTZtdXbyDjIQJaN0HK4hicGVc1t1d1iB81KFfUVpX8/QztdB58Q9A== + dependencies: + "@nrwl/tao" "19.4.0" + "@yarnpkg/lockfile" "^1.1.0" + "@yarnpkg/parsers" "3.0.0-rc.46" + "@zkochan/js-yaml" "0.0.7" + axios "^1.6.0" + chalk "^4.1.0" + cli-cursor "3.1.0" + cli-spinners "2.6.1" + cliui "^8.0.1" + dotenv "~16.4.5" + dotenv-expand "~11.0.6" + enquirer "~2.3.6" + figures "3.2.0" + flat "^5.0.2" + front-matter "^4.0.2" + fs-extra "^11.1.0" + ignore "^5.0.4" + jest-diff "^29.4.1" + jsonc-parser "3.2.0" + lines-and-columns "~2.0.3" + minimatch "9.0.3" + node-machine-id "1.1.12" + npm-run-path "^4.0.1" + open "^8.4.0" + ora "5.3.0" + semver "^7.5.3" + string-width "^4.2.3" + strong-log-transformer "^2.1.0" + tar-stream "~2.2.0" + tmp "~0.2.1" + tsconfig-paths "^4.1.2" + tslib "^2.3.0" + yargs "^17.6.2" + yargs-parser "21.1.1" + optionalDependencies: + "@nx/nx-darwin-arm64" "19.4.0" + "@nx/nx-darwin-x64" "19.4.0" + "@nx/nx-freebsd-x64" "19.4.0" + "@nx/nx-linux-arm-gnueabihf" "19.4.0" + "@nx/nx-linux-arm64-gnu" "19.4.0" + "@nx/nx-linux-arm64-musl" "19.4.0" + "@nx/nx-linux-x64-gnu" "19.4.0" + "@nx/nx-linux-x64-musl" "19.4.0" + "@nx/nx-win32-arm64-msvc" "19.4.0" + "@nx/nx-win32-x64-msvc" "19.4.0" + +nx@19.4.2: + version "19.4.2" + resolved "https://registry.yarnpkg.com/nx/-/nx-19.4.2.tgz#c627acebb1ad70766fae5b971006468fe3024787" + integrity sha512-h4NMoy9uvSHuM+kyioZXb5G4hfBZ7E4a5dswG2RPe3g/GcY9wdpkUMd/EJJ0cHQwv36kRZOMCflhounYCd7OeA== + dependencies: + "@nrwl/tao" "19.4.2" + "@yarnpkg/lockfile" "^1.1.0" + "@yarnpkg/parsers" "3.0.0-rc.46" + "@zkochan/js-yaml" "0.0.7" + axios "^1.6.0" + chalk "^4.1.0" + cli-cursor "3.1.0" + cli-spinners "2.6.1" + cliui "^8.0.1" + dotenv "~16.4.5" + dotenv-expand "~11.0.6" + enquirer "~2.3.6" + figures "3.2.0" + flat "^5.0.2" + front-matter "^4.0.2" + fs-extra "^11.1.0" + ignore "^5.0.4" + jest-diff "^29.4.1" + jsonc-parser "3.2.0" + lines-and-columns "~2.0.3" + minimatch "9.0.3" + node-machine-id "1.1.12" + npm-run-path "^4.0.1" + open "^8.4.0" + ora "5.3.0" + semver "^7.5.3" + string-width "^4.2.3" + strong-log-transformer "^2.1.0" + tar-stream "~2.2.0" + tmp "~0.2.1" + tsconfig-paths "^4.1.2" + tslib "^2.3.0" + yargs "^17.6.2" + yargs-parser "21.1.1" + optionalDependencies: + "@nx/nx-darwin-arm64" "19.4.2" + "@nx/nx-darwin-x64" "19.4.2" + "@nx/nx-freebsd-x64" "19.4.2" + "@nx/nx-linux-arm-gnueabihf" "19.4.2" + "@nx/nx-linux-arm64-gnu" "19.4.2" + "@nx/nx-linux-arm64-musl" "19.4.2" + "@nx/nx-linux-x64-gnu" "19.4.2" + "@nx/nx-linux-x64-musl" "19.4.2" + "@nx/nx-win32-arm64-msvc" "19.4.2" + "@nx/nx-win32-x64-msvc" "19.4.2" + +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +open@^8.4.0: + version "8.4.2" + resolved "https://registry.npmjs.org/open/-/open-8.4.2.tgz" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +open@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" + integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== + dependencies: + default-browser "^4.0.0" + define-lazy-prop "^3.0.0" + is-inside-container "^1.0.0" + is-wsl "^2.2.0" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +ora@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.3.0.tgz#fb832899d3a1372fe71c8b2c534bbfe74961bb6f" + integrity sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g== + dependencies: + bl "^4.0.3" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + log-symbols "^4.0.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +oxc-resolver@^1.9.2: + version "1.9.3" + resolved "https://registry.yarnpkg.com/oxc-resolver/-/oxc-resolver-1.9.3.tgz#f8e4bf8072fdaa71e0da3fc6b7c4759fef3ad4db" + integrity sha512-ROO5IGjFp5e150IDCzFvE3xtTrbO6jytAugfEHegF0ym2Ww+lRxP0cAwFGCR1021aWUhrC8VjZXOdTocg+Qthw== + optionalDependencies: + "@oxc-resolver/binding-darwin-arm64" "1.9.3" + "@oxc-resolver/binding-darwin-x64" "1.9.3" + "@oxc-resolver/binding-linux-arm-gnueabihf" "1.9.3" + "@oxc-resolver/binding-linux-arm64-gnu" "1.9.3" + "@oxc-resolver/binding-linux-arm64-musl" "1.9.3" + "@oxc-resolver/binding-linux-x64-gnu" "1.9.3" + "@oxc-resolver/binding-linux-x64-musl" "1.9.3" + "@oxc-resolver/binding-wasm32-wasi" "1.9.3" + "@oxc-resolver/binding-win32-arm64-msvc" "1.9.3" + "@oxc-resolver/binding-win32-x64-msvc" "1.9.3" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-to-regexp@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" + integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4, pirates@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@3.3.2, prettier@^3.2.5: + version "3.3.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" + integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== + +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +proc-log@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz" + integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +pure-rand@^6.0.0: + version "6.0.2" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz" + integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +react-is@^18.0.0: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" + integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.0.0, resolve@^1.20.0: + version "1.22.2" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^1.12.0, resolve@^1.14.2: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-applescript@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" + integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== + dependencies: + execa "^5.0.0" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@1.2.1, sax@>=0.6.0: + version "1.2.1" + resolved "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz" + integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== + +semver@^5.4.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.0.0, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shimmer@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" + integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sinon@^16.1.3: + version "16.1.3" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-16.1.3.tgz#b760ddafe785356e2847502657b4a0da5501fba8" + integrity sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA== + dependencies: + "@sinonjs/commons" "^3.0.0" + "@sinonjs/fake-timers" "^10.3.0" + "@sinonjs/samsam" "^8.0.0" + diff "^5.1.0" + nise "^5.1.4" + supports-color "^7.2.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@0.5.19: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.5.12, source-map-support@^0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-chain@^1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" + integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +strip-json-comments@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +strong-log-transformer@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz" + integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA== + dependencies: + duplexer "^0.1.1" + minimist "^1.2.0" + through "^2.3.4" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0, supports-color@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +synckit@^0.8.6: + version "0.8.6" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.6.tgz#b69b7fbce3917c2673cbdc0d87fb324db4a5b409" + integrity sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA== + dependencies: + "@pkgr/utils" "^2.4.2" + tslib "^2.6.2" + +tar-stream@~2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +through@^2.3.4: + version "2.3.8" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +titleize@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" + integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== + +tmp@~0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + +ts-api-utils@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== + +ts-essentials@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-10.0.1.tgz#edee9a06e8a1a7e33ef21ae223d908a7c646e6c5" + integrity sha512-HPH+H2bkkO8FkMDau+hFvv7KYozzned9Zr1Urn7rRPXMF4mZmCKOq+u4AI1AAW+2bofIOXTuSdKo9drQuni2dQ== + +ts-jest@^29.1.0: + version "29.1.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.5.tgz#d6c0471cc78bffa2cb4664a0a6741ef36cfe8f69" + integrity sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-node-dev@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-2.0.0.tgz" + integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== + dependencies: + chokidar "^3.5.1" + dynamic-dedupe "^0.3.0" + minimist "^1.2.6" + mkdirp "^1.0.4" + resolve "^1.0.0" + rimraf "^2.6.1" + source-map-support "^0.5.12" + tree-kill "^1.2.2" + ts-node "^10.4.0" + tsconfig "^7.0.0" + +ts-node@10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +ts-node@^10.4.0, ts-node@^10.9.1: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tsconfig-paths@^4.1.2: + version "4.2.0" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tsconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz" + integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== + dependencies: + "@types/strip-bom" "^3.0.0" + "@types/strip-json-comments" "0.0.30" + strip-bom "^3.0.0" + strip-json-comments "^2.0.0" + +tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.6.2, tslib@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typescript@^5.4.5: + version "5.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" + integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== + +typescript@~5.4.2: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +universal-github-app-jwt@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.2.tgz#8c1867a394d7d9d42cda34f11d1bcb023797d8df" + integrity sha512-t1iB2FmLFE+yyJY9+3wMx0ejB+MQpEVkH0gQv7dR6FZyltyq+ZZO0uDpbopxhrZ3SLEO4dCEkIujOMldEQ2iOA== + dependencies: + "@types/jsonwebtoken" "^9.0.0" + jsonwebtoken "^9.0.2" + +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +untildify@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" + integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url@0.10.3: + version "0.10.3" + resolved "https://registry.npmjs.org/url/-/url-0.10.3.tgz" + integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@^0.12.4: + version "0.12.5" + resolved "https://registry.npmjs.org/util/-/util-0.12.5.tgz" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz" + integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== + +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.1.0" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz" + integrity sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + +validate-npm-package-name@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz" + integrity sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ== + dependencies: + builtins "^5.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +watchpack@^2.0.0-beta.10: + version "2.4.0" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wcwidth@^1.0.0, wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +which-typed-array@^1.1.2: + version "1.1.9" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +xml2js@0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@21.1.1, yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1, yargs@^17.6.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/main.tf b/main.tf index d53bebea36..b1a0e6bbea 100644 --- a/main.tf +++ b/main.tf @@ -8,8 +8,9 @@ locals { key_base64 = module.ssm.parameters.github_app_key_base64 } - default_runner_labels = "self-hosted,${var.runner_os},${var.runner_architecture}" - runner_labels = var.runner_extra_labels != "" ? "${local.default_runner_labels},${var.runner_extra_labels}" : local.default_runner_labels + runner_labels = sort(distinct(concat(["self-hosted", var.runner_os, var.runner_architecture], var.runner_extra_labels))) + + ssm_root_path = var.ssm_paths.use_prefix ? "/${var.ssm_paths.root}/${var.prefix}" : "/${var.ssm_paths.root}" } resource "random_string" "random" { @@ -57,13 +58,13 @@ resource "aws_sqs_queue_policy" "webhook_events_workflow_job_queue_policy" { } resource "aws_sqs_queue" "queued_builds" { - name = "${var.prefix}-queued-builds${var.fifo_build_queue ? ".fifo" : ""}" + name = "${var.prefix}-queued-builds${var.enable_fifo_build_queue ? ".fifo" : ""}" delay_seconds = var.delay_webhook_event visibility_timeout_seconds = var.runners_scale_up_lambda_timeout message_retention_seconds = var.job_queue_retention_in_seconds - fifo_queue = var.fifo_build_queue + fifo_queue = var.enable_fifo_build_queue receive_wait_time_seconds = 0 - content_based_deduplication = var.fifo_build_queue + content_based_deduplication = var.enable_fifo_build_queue redrive_policy = var.redrive_build_queue.enabled ? jsonencode({ deadLetterTargetArn = aws_sqs_queue.queued_builds_dlq[0].arn, maxReceiveCount = var.redrive_build_queue.maxReceiveCount @@ -102,12 +103,12 @@ resource "aws_sqs_queue_policy" "build_queue_dlq_policy" { resource "aws_sqs_queue" "queued_builds_dlq" { count = var.redrive_build_queue.enabled ? 1 : 0 - name = "${var.prefix}-queued-builds_dead_letter${var.fifo_build_queue ? ".fifo" : ""}" + name = "${var.prefix}-queued-builds_dead_letter${var.enable_fifo_build_queue ? ".fifo" : ""}" sqs_managed_sse_enabled = var.queue_encryption.sqs_managed_sse_enabled kms_master_key_id = var.queue_encryption.kms_master_key_id kms_data_key_reuse_period_seconds = var.queue_encryption.kms_data_key_reuse_period_seconds - fifo_queue = var.fifo_build_queue + fifo_queue = var.enable_fifo_build_queue tags = var.tags } @@ -115,22 +116,38 @@ module "ssm" { source = "./modules/ssm" kms_key_arn = var.kms_key_arn - prefix = var.prefix + path_prefix = "${local.ssm_root_path}/${var.ssm_paths.app}" github_app = var.github_app tags = local.tags } module "webhook" { source = "./modules/webhook" + ssm_paths = { + root = local.ssm_root_path + webhook = var.ssm_paths.webhook + } + prefix = var.prefix + tags = local.tags + kms_key_arn = var.kms_key_arn - aws_region = var.aws_region - prefix = var.prefix - tags = local.tags - kms_key_arn = var.kms_key_arn - sqs_build_queue = aws_sqs_queue.queued_builds - sqs_build_queue_fifo = var.fifo_build_queue - sqs_workflow_job_queue = length(aws_sqs_queue.webhook_events_workflow_job_queue) > 0 ? aws_sqs_queue.webhook_events_workflow_job_queue[0] : null - github_app_webhook_secret_arn = module.ssm.parameters.github_app_webhook_secret.arn + runner_matcher_config = { + (aws_sqs_queue.queued_builds.id) = { + id : aws_sqs_queue.queued_builds.id + arn : aws_sqs_queue.queued_builds.arn + fifo : var.enable_fifo_build_queue + matcherConfig : { + labelMatchers : [local.runner_labels] + exactMatch : var.enable_runner_workflow_job_labels_check_all + } + } + } + matcher_config_parameter_store_tier = var.matcher_config_parameter_store_tier + sqs_workflow_job_queue = length(aws_sqs_queue.webhook_events_workflow_job_queue) > 0 ? aws_sqs_queue.webhook_events_workflow_job_queue[0] : null + + github_app_parameters = { + webhook_secret = module.ssm.parameters.github_app_webhook_secret + } lambda_s3_bucket = var.lambda_s3_bucket webhook_lambda_s3_key = var.webhook_lambda_s3_key @@ -139,19 +156,21 @@ module "webhook" { lambda_runtime = var.lambda_runtime lambda_architecture = var.lambda_architecture lambda_zip = var.webhook_lambda_zip + lambda_memory_size = var.webhook_lambda_memory_size lambda_timeout = var.webhook_lambda_timeout + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config logging_retention_in_days = var.logging_retention_in_days logging_kms_key_id = var.logging_kms_key_id - # labels - enable_workflow_job_labels_check = var.runner_enable_workflow_job_labels_check - workflow_job_labels_check_all = var.runner_enable_workflow_job_labels_check_all - runner_labels = local.runner_labels - role_path = var.role_path - role_permissions_boundary = var.role_permissions_boundary - repository_white_list = var.repository_white_list + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + repository_white_list = var.repository_white_list + + lambda_subnet_ids = var.lambda_subnet_ids + lambda_security_group_ids = var.lambda_security_group_ids + aws_partition = var.aws_partition - log_type = var.log_type log_level = var.log_level } @@ -165,6 +184,12 @@ module "runners" { prefix = var.prefix tags = local.tags + ssm_paths = { + root = local.ssm_root_path + tokens = "${var.ssm_paths.runners}/tokens" + config = "${var.ssm_paths.runners}/config" + } + s3_runner_binaries = var.enable_runner_binaries_syncer ? { arn = module.runner_binaries[0].bucket.arn id = module.runner_binaries[0].bucket.id @@ -182,19 +207,22 @@ module "runners" { ami_filter = var.ami_filter ami_owners = var.ami_owners ami_id_ssm_parameter_name = var.ami_id_ssm_parameter_name + ami_kms_key_arn = var.ami_kms_key_arn sqs_build_queue = aws_sqs_queue.queued_builds github_app_parameters = local.github_app_parameters enable_organization_runners = var.enable_organization_runners enable_ephemeral_runners = var.enable_ephemeral_runners + enable_jit_config = var.enable_jit_config enable_job_queued_check = var.enable_job_queued_check + enable_on_demand_failover_for_errors = var.enable_runner_on_demand_failover_for_errors disable_runner_autoupdate = var.disable_runner_autoupdate enable_managed_runner_security_group = var.enable_managed_runner_security_group enable_runner_detailed_monitoring = var.enable_runner_detailed_monitoring scale_down_schedule_expression = var.scale_down_schedule_expression minimum_running_time_in_minutes = var.minimum_running_time_in_minutes runner_boot_time_in_minutes = var.runner_boot_time_in_minutes - runner_extra_labels = var.runner_extra_labels + runner_labels = local.runner_labels runner_as_root = var.runner_as_root runner_run_as = var.runner_run_as runners_maximum_count = var.runners_maximum_count @@ -203,6 +231,7 @@ module "runners" { egress_rules = var.runner_egress_rules runner_additional_security_group_ids = var.runner_additional_security_group_ids metadata_options = var.runner_metadata_options + credit_specification = var.runner_credit_specification enable_runner_binaries_syncer = var.enable_runner_binaries_syncer lambda_s3_bucket = var.lambda_s3_bucket @@ -211,26 +240,34 @@ module "runners" { lambda_runtime = var.lambda_runtime lambda_architecture = var.lambda_architecture lambda_zip = var.runners_lambda_zip + lambda_scale_up_memory_size = coalesce(var.runners_scale_up_Lambda_memory_size, var.runners_scale_up_lambda_memory_size) + lambda_scale_down_memory_size = var.runners_scale_down_lambda_memory_size lambda_timeout_scale_up = var.runners_scale_up_lambda_timeout lambda_timeout_scale_down = var.runners_scale_down_lambda_timeout lambda_subnet_ids = var.lambda_subnet_ids lambda_security_group_ids = var.lambda_security_group_ids + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config logging_retention_in_days = var.logging_retention_in_days logging_kms_key_id = var.logging_kms_key_id enable_cloudwatch_agent = var.enable_cloudwatch_agent cloudwatch_config = var.cloudwatch_config runner_log_files = var.runner_log_files runner_group_name = var.runner_group_name + runner_name_prefix = var.runner_name_prefix scale_up_reserved_concurrent_executions = var.scale_up_reserved_concurrent_executions + associate_public_ipv4_address = var.associate_public_ipv4_address + instance_profile_path = var.instance_profile_path role_path = var.role_path role_permissions_boundary = var.role_permissions_boundary - enabled_userdata = var.enabled_userdata + enable_userdata = var.enable_userdata enable_user_data_debug_logging = var.enable_user_data_debug_logging_runner userdata_template = var.userdata_template + userdata_content = var.userdata_content userdata_pre_install = var.userdata_pre_install userdata_post_install = var.userdata_post_install key_name = var.key_name @@ -245,13 +282,16 @@ module "runners" { kms_key_arn = var.kms_key_arn - log_type = var.log_type log_level = var.log_level pool_config = var.pool_config + pool_lambda_memory_size = var.pool_lambda_memory_size pool_lambda_timeout = var.pool_lambda_timeout pool_runner_owner = var.pool_runner_owner pool_lambda_reserved_concurrent_executions = var.pool_lambda_reserved_concurrent_executions + + ssm_housekeeper = var.runners_ssm_housekeeper + ebs_optimized = var.runners_ebs_optimized } module "runner_binaries" { @@ -259,17 +299,15 @@ module "runner_binaries" { source = "./modules/runner-binaries-syncer" - aws_region = var.aws_region - prefix = var.prefix - tags = local.tags + prefix = var.prefix + tags = local.tags - distribution_bucket_name = "${var.prefix}-dist-${random_string.random.result}" + distribution_bucket_name = lower("${var.prefix}-dist-${random_string.random.result}") s3_logging_bucket = var.runner_binaries_s3_logging_bucket s3_logging_bucket_prefix = var.runner_binaries_s3_logging_bucket_prefix - runner_os = var.runner_os - runner_architecture = var.runner_architecture - runner_allow_prerelease_binaries = var.runner_allow_prerelease_binaries + runner_os = var.runner_os + runner_architecture = var.runner_architecture lambda_s3_bucket = var.lambda_s3_bucket syncer_lambda_s3_key = var.syncer_lambda_s3_key @@ -277,20 +315,87 @@ module "runner_binaries" { lambda_runtime = var.lambda_runtime lambda_architecture = var.lambda_architecture lambda_zip = var.runner_binaries_syncer_lambda_zip + lambda_memory_size = var.runner_binaries_syncer_lambda_memory_size lambda_timeout = var.runner_binaries_syncer_lambda_timeout + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config logging_retention_in_days = var.logging_retention_in_days logging_kms_key_id = var.logging_kms_key_id + state_event_rule_binaries_syncer = var.state_event_rule_binaries_syncer server_side_encryption_configuration = var.runner_binaries_s3_sse_configuration + s3_versioning = var.runner_binaries_s3_versioning role_path = var.role_path role_permissions_boundary = var.role_permissions_boundary - log_type = var.log_type log_level = var.log_level lambda_subnet_ids = var.lambda_subnet_ids lambda_security_group_ids = var.lambda_security_group_ids + aws_partition = var.aws_partition lambda_principals = var.lambda_principals } + +module "ami_housekeeper" { + count = var.enable_ami_housekeeper ? 1 : 0 + source = "./modules/ami-housekeeper" + + prefix = var.prefix + tags = local.tags + aws_partition = var.aws_partition + + lambda_zip = var.ami_housekeeper_lambda_zip + lambda_s3_bucket = var.lambda_s3_bucket + lambda_s3_key = var.ami_housekeeper_lambda_s3_key + lambda_s3_object_version = var.ami_housekeeper_lambda_s3_object_version + + lambda_architecture = var.lambda_architecture + lambda_principals = var.lambda_principals + lambda_runtime = var.lambda_runtime + lambda_security_group_ids = var.lambda_security_group_ids + lambda_subnet_ids = var.lambda_subnet_ids + lambda_timeout = var.ami_housekeeper_lambda_timeout + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config + + logging_retention_in_days = var.logging_retention_in_days + logging_kms_key_id = var.logging_kms_key_id + log_level = var.log_level + + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + + cleanup_config = var.ami_housekeeper_cleanup_config + lambda_schedule_expression = var.ami_housekeeper_lambda_schedule_expression +} + +locals { + lambda_instance_termination_watcher = { + prefix = var.prefix + tags = local.tags + aws_partition = var.aws_partition + architecture = var.lambda_architecture + principals = var.lambda_principals + runtime = var.lambda_runtime + security_group_ids = var.lambda_security_group_ids + subnet_ids = var.lambda_subnet_ids + lambda_tags = var.lambda_tags + log_level = var.log_level + logging_kms_key_id = var.logging_kms_key_id + logging_retention_in_days = var.logging_retention_in_days + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + metrics_namespace = var.metrics_namespace + s3_bucket = var.lambda_s3_bucket + tracing_config = var.tracing_config + } +} + +module "instance_termination_watcher" { + source = "./modules/termination-watcher" + count = var.instance_termination_watcher.enable ? 1 : 0 + + config = merge(local.lambda_instance_termination_watcher, var.instance_termination_watcher) +} diff --git a/mkdocs.yaml b/mkdocs.yaml new file mode 100644 index 0000000000..75aa49a1f6 --- /dev/null +++ b/mkdocs.yaml @@ -0,0 +1,74 @@ +site_name: GitHub Runners on AWS + +repo_name: philips-labs/terraform-aws-github-runner +repo_url: https://github.com/philips-labs/terraform-aws-github-runner +edit_uri: edit/main/docs/ +use_directory_urls: true + + + +theme: + name: material + icon: + logo: material/rocket-launch-outline + palette: + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/weather-night + name: Switch to system preference + - scheme: default + toggle: + icon: material/weather-sunny + name: Switch to dark mode + features: + - content.code.copy + - content.action.edit + - navigation.instant + - navigation.instant.progress + - navigation.tracking + - pymdownx.snippets + - navigation.footer + +extra: + status: + new: Recently added + deprecated: Deprecated + social: + - icon: fontawesome/brands/github + link: https://github.com/philips-labs/terraform-aws-github-runner + + +markdown_extensions: + - pymdownx.snippets: + check_paths: true + - pymdownx.emoji: + +nav: + - Introduction: index.md + - Configuration: configuration.md + - Getting started: getting-started.md + - Security: security.md + - Modules: + - Runners (root): modules/runners.md + - Multi Runners: modules/public/multi-runner.md + - AMI Housekeeper: modules/public/ami-housekeeper.md + - Lambda Downloader: modules/public/download-lambda.md + - Setup IAM permissions: modules/public/setup-iam-permissions.md + - Internal: + - Runners: modules/internal/runners.md + - Syncer: modules/internal/runner-binaries-syncer.md + - SSM: modules/internal/ssm.md + - Webhook: modules/internal/webhook.md + - Update Webhook: modules/internal/webhook-github-app.md + - Examples: + - Overview: examples/index.md + - Default: examples/default.md + - Multi Runner: examples/multi-runner.md + - Ephemeral: examples/ephemeral.md + - ARM64: examples/arm64.md + - Windows: examples/windows.md + - Custom AMI: examples/prebuilt.md + - Lambda download: examples/lambda-download.md + - Permissions boundary: examples/permissions-boundary.md + - AMI examples: ami-examples/index.md diff --git a/modules/ami-housekeeper/README.md b/modules/ami-housekeeper/README.md new file mode 100644 index 0000000000..d052cf82de --- /dev/null +++ b/modules/ami-housekeeper/README.md @@ -0,0 +1,135 @@ +# Module - AMI Housekeeper + +This module deploys a Lambda function responsible for deleting outdated AMIs. You can specify various criteria for the deletion process. Please note that the creation of AMIs is not within the scope of this project; the Lambda's role is solely to remove old ones. To avoid potential conflicts, it is recommended to deploy this module only once. + +By default, the Lambda will scan all launch templates and assume that only the default version is in use. Any other AMIs referenced in the launch templates will be considered outdated and subject to deletion. Additionally, the module can search for AMIs referenced in AWS Systems Manager (SSM). When you set ssmParameterNames to *ami-id, the module will regard all AMIs referenced in SSM as in use, sparing them from deletion. + +You can further refine the deletion process by applying AMI filters, such as those based on tags. The module also offers a 'dry run' option, allowing you to test the Lambda's behavior before executing actual deletions. + +## Usages + +The module can be activated via the main module by setting `enable_ami_housekeeper` to `true`. Or invoking the module directly. + +``` +module "ami_housekeeper" { + source = "path to module" + + prefix = "my-prefix" + + ami_cleanup_config = { + ssmParameterNames = ["*/ami-id"] + minimumDaysOld = 30 + filters = [ + { + Name = "tag:Packer" + Values = ["true"] + } + ] + dryRun = true + } + + log_level = "debug" +} +``` + +## Development + +## Lambda Function + +The Lambda function is written in [TypeScript](https://www.typescriptlang.org/) and requires Node and yarn. Sources are located in [https://github.com/philips-labs/terraform-aws-github-runner/tree/main/lambdas]. + +### Install + +```bash +cd lambdas +yarn install +``` + +### Test + +Test are implemented with [Jest](https://jestjs.io/), calls to AWS and GitHub are mocked. + +```bash +yarn run test +``` + +### Package + +To compile all TypeScript/JavaScript sources in a single file [ncc](https://github.com/zeit/ncc) is used. + +```bash +yarn run dist +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.27 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_event_rule.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_target.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_log_group.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.ami_housekeeper_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.lambda_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.ami_housekeeper_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_lambda_function.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_permission.ami_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_partition](#input\_aws\_partition) | (optional) partition for the base arn if not 'aws' | `string` | `"aws"` | no | +| [cleanup\_config](#input\_cleanup\_config) | Configuration for AMI cleanup.

`amiFilters` - Filters to use when searching for AMIs to cleanup. Default filter for images owned by the account and that are available.
`dryRun` - If true, no AMIs will be deregistered. Default false.
`launchTemplateNames` - Launch template names to use when searching for AMIs to cleanup. Default no launch templates.
`maxItems` - The maximum numer of AMI's tha will be queried for cleanup. Default no maximum.
`minimumDaysOld` - Minimum number of days old an AMI must be to be considered for cleanup. Default 30.
`ssmParameterNames` - SSM parameter names to use when searching for AMIs to cleanup. This parameter should be set when using SSM to configure the AMI to use. Default no SSM parameters. |
object({
amiFilters = optional(list(object({
Name = string
Values = list(string)
})),
[{
Name : "state",
Values : ["available"],
},
{
Name : "image-type",
Values : ["machine"],
}]
)
dryRun = optional(bool, false)
launchTemplateNames = optional(list(string))
maxItems = optional(number)
minimumDaysOld = optional(number, 30)
ssmParameterNames = optional(list(string))
})
| `{}` | no | +| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"arm64"` | no | +| [lambda\_memory\_size](#input\_lambda\_memory\_size) | Memory size linit in MB of the lambda. | `number` | `256` | no | +| [lambda\_principals](#input\_lambda\_principals) | (Optional) add extra principals to the role created for execution of the lambda, e.g. for local testing. |
list(object({
type = string
identifiers = list(string)
}))
| `[]` | no | +| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs20.x"` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `string` | `null` | no | +| [lambda\_s3\_key](#input\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [lambda\_s3\_object\_version](#input\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [lambda\_schedule\_expression](#input\_lambda\_schedule\_expression) | Scheduler expression for action runner binary syncer. | `string` | `"rate(1 day)"` | no | +| [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | +| [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_tags](#input\_lambda\_tags) | Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags. | `map(string)` | `{}` | no | +| [lambda\_timeout](#input\_lambda\_timeout) | Time out of the lambda in seconds. | `number` | `60` | no | +| [lambda\_zip](#input\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | +| [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | +| [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with | `string` | `null` | no | +| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | +| [prefix](#input\_prefix) | The prefix used for naming resources | `string` | `"github-actions"` | no | +| [role\_path](#input\_role\_path) | The path that will be added to the role, if not set the environment name will be used. | `string` | `null` | no | +| [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | +| [state\_event\_rule\_ami\_housekeeper](#input\_state\_event\_rule\_ami\_housekeeper) | State of the rule. | `string` | `"ENABLED"` | no | +| [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [lambda](#output\_lambda) | n/a | +| [lambda\_log\_group](#output\_lambda\_log\_group) | n/a | +| [lambda\_role](#output\_lambda\_role) | n/a | + diff --git a/modules/ami-housekeeper/ami.tf b/modules/ami-housekeeper/ami.tf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/ami-housekeeper/iam.tf b/modules/ami-housekeeper/iam.tf new file mode 100644 index 0000000000..454d943b4b --- /dev/null +++ b/modules/ami-housekeeper/iam.tf @@ -0,0 +1,16 @@ +data "aws_iam_policy_document" "lambda_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + statement { + actions = [ + "xray:BatchGetTraces", + "xray:GetTraceSummaries", + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ] + effect = "Allow" + resources = [ + "*" + ] + sid = "AllowXRay" + } +} diff --git a/modules/ami-housekeeper/main.tf b/modules/ami-housekeeper/main.tf new file mode 100644 index 0000000000..a1e66c24ef --- /dev/null +++ b/modules/ami-housekeeper/main.tf @@ -0,0 +1,132 @@ +locals { + lambda_zip = var.lambda_zip == null ? "${path.module}/../../lambdas/functions/ami-housekeeper/ami-housekeeper.zip" : var.lambda_zip + role_path = var.role_path == null ? "/${var.prefix}/" : var.role_path +} + +resource "aws_lambda_function" "ami_housekeeper" { + s3_bucket = var.lambda_s3_bucket != null ? var.lambda_s3_bucket : null + s3_key = var.lambda_s3_key != null ? var.lambda_s3_key : null + s3_object_version = var.lambda_s3_object_version != null ? var.lambda_s3_object_version : null + filename = var.lambda_s3_bucket == null ? local.lambda_zip : null + source_code_hash = var.lambda_s3_bucket == null ? filebase64sha256(local.lambda_zip) : null + function_name = "${var.prefix}-ami-housekeeper" + role = aws_iam_role.ami_housekeeper.arn + handler = "index.handler" + runtime = var.lambda_runtime + timeout = var.lambda_timeout + memory_size = var.lambda_memory_size + architectures = [var.lambda_architecture] + + environment { + variables = { + LOG_LEVEL = var.log_level + POWERTOOLS_LOGGER_LOG_EVENT = var.log_level == "debug" ? "true" : "false" + AMI_CLEANUP_OPTIONS = jsonencode(var.cleanup_config) + POWERTOOLS_SERVICE_NAME = "ami-housekeeper" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error + } + } + + dynamic "vpc_config" { + for_each = var.lambda_subnet_ids != null && var.lambda_security_group_ids != null ? [true] : [] + content { + security_group_ids = var.lambda_security_group_ids + subnet_ids = var.lambda_subnet_ids + } + } + + tags = merge(var.tags, var.lambda_tags) + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } +} + +resource "aws_cloudwatch_log_group" "ami_housekeeper" { + name = "/aws/lambda/${aws_lambda_function.ami_housekeeper.function_name}" + retention_in_days = var.logging_retention_in_days + kms_key_id = var.logging_kms_key_id + tags = var.tags +} + +resource "aws_iam_role" "ami_housekeeper" { + name = "${var.prefix}-ami-housekeeper-role" + assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json + path = local.role_path + permissions_boundary = var.role_permissions_boundary + + tags = var.tags +} + +data "aws_iam_policy_document" "lambda_assume_role_policy" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["lambda.amazonaws.com"] + } + + dynamic "principals" { + for_each = var.lambda_principals + + content { + type = principals.value.type + identifiers = principals.value.identifiers + } + } + } +} + +resource "aws_iam_role_policy" "lambda_logging" { + name = "${var.prefix}-lambda-logging-policy-ami-housekeeper" + role = aws_iam_role.ami_housekeeper.id + + policy = templatefile("${path.module}/policies/lambda-cloudwatch.json", { + log_group_arn = aws_cloudwatch_log_group.ami_housekeeper.arn + }) +} + +resource "aws_iam_role_policy" "ami_housekeeper" { + name = "${var.prefix}-lambda-ami-policy" + role = aws_iam_role.ami_housekeeper.id + + policy = templatefile("${path.module}/policies/lambda-ami-housekeeper.json", {}) +} + +resource "aws_cloudwatch_event_rule" "ami_housekeeper" { + name = "${var.prefix}-ami-housekeeper-rule" + schedule_expression = var.lambda_schedule_expression + tags = var.tags + state = var.state_event_rule_ami_housekeeper +} + +resource "aws_cloudwatch_event_target" "ami_housekeeper" { + rule = aws_cloudwatch_event_rule.ami_housekeeper.name + arn = aws_lambda_function.ami_housekeeper.arn +} + +resource "aws_iam_role_policy_attachment" "ami_housekeeper_vpc_execution_role" { + count = length(var.lambda_subnet_ids) > 0 ? 1 : 0 + role = aws_iam_role.ami_housekeeper.name + policy_arn = "arn:${var.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" +} + +resource "aws_lambda_permission" "ami_housekeeper" { + statement_id = "AllowExecutionFromCloudWatch" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.ami_housekeeper.function_name + principal = "events.amazonaws.com" + source_arn = aws_cloudwatch_event_rule.ami_housekeeper.arn +} + +resource "aws_iam_role_policy" "ami_housekeeper_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.ami_housekeeper.name +} diff --git a/modules/ami-housekeeper/outputs.tf b/modules/ami-housekeeper/outputs.tf new file mode 100644 index 0000000000..8fcd7f4e5e --- /dev/null +++ b/modules/ami-housekeeper/outputs.tf @@ -0,0 +1,11 @@ +output "lambda" { + value = aws_lambda_function.ami_housekeeper +} + +output "lambda_log_group" { + value = aws_cloudwatch_log_group.ami_housekeeper +} + +output "lambda_role" { + value = aws_iam_role.ami_housekeeper +} diff --git a/modules/ami-housekeeper/policies/lambda-ami-housekeeper.json b/modules/ami-housekeeper/policies/lambda-ami-housekeeper.json new file mode 100644 index 0000000000..d13355717c --- /dev/null +++ b/modules/ami-housekeeper/policies/lambda-ami-housekeeper.json @@ -0,0 +1,19 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeImages", + "ec2:DescribeSnapshots", + "ec2:DescribeLaunchTemplates", + "ec2:DescribeLaunchTemplateVersions", + "ec2:DeregisterImage", + "ec2:DeleteSnapshot", + "ssm:DescribeParameters", + "ssm:GetParameter" + ], + "Resource": "*" + } + ] +} diff --git a/modules/ami-housekeeper/policies/lambda-cloudwatch.json b/modules/ami-housekeeper/policies/lambda-cloudwatch.json new file mode 100644 index 0000000000..ad9246bcb3 --- /dev/null +++ b/modules/ami-housekeeper/policies/lambda-cloudwatch.json @@ -0,0 +1,10 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["logs:CreateLogStream", "logs:PutLogEvents"], + "Resource": "${log_group_arn}*" + } + ] +} diff --git a/modules/ami-housekeeper/policies/lambda-kms.json b/modules/ami-housekeeper/policies/lambda-kms.json new file mode 100644 index 0000000000..63263926e5 --- /dev/null +++ b/modules/ami-housekeeper/policies/lambda-kms.json @@ -0,0 +1,10 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["kms:GenerateDataKey", "kms:Decrypt"], + "Resource": "${kms_key_arn}" + } + ] + } \ No newline at end of file diff --git a/modules/ami-housekeeper/variables.tf b/modules/ami-housekeeper/variables.tf new file mode 100644 index 0000000000..93a2f862ea --- /dev/null +++ b/modules/ami-housekeeper/variables.tf @@ -0,0 +1,200 @@ +# generic variables for lambda + +variable "tags" { + description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." + type = map(string) + default = {} +} + +variable "prefix" { + description = "The prefix used for naming resources" + type = string + default = "github-actions" +} + +variable "lambda_zip" { + description = "File location of the lambda zip file." + type = string + default = null +} + +variable "lambda_timeout" { + description = "Time out of the lambda in seconds." + type = number + default = 60 +} + +variable "lambda_memory_size" { + description = "Memory size linit in MB of the lambda." + type = number + default = 256 +} + +variable "role_permissions_boundary" { + description = "Permissions boundary that will be added to the created role for the lambda." + type = string + default = null +} + +variable "role_path" { + description = "The path that will be added to the role, if not set the environment name will be used." + type = string + default = null +} + +variable "logging_retention_in_days" { + description = "Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653." + type = number + default = 180 +} + +variable "logging_kms_key_id" { + description = "Specifies the kms key id to encrypt the logs with" + type = string + default = null +} + +variable "lambda_subnet_ids" { + description = "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`." + type = list(string) + default = [] +} + +variable "lambda_security_group_ids" { + description = "List of security group IDs associated with the Lambda function." + type = list(string) + default = [] +} + +variable "aws_partition" { + description = "(optional) partition for the base arn if not 'aws'" + type = string + default = "aws" +} + +variable "log_level" { + description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + type = string + default = "info" + validation { + condition = anytrue([ + var.log_level == "debug", + var.log_level == "info", + var.log_level == "warn", + var.log_level == "error", + ]) + error_message = "`log_level` value not valid. Valid values are 'debug', 'info', 'warn', 'error'." + } +} + +variable "lambda_principals" { + description = "(Optional) add extra principals to the role created for execution of the lambda, e.g. for local testing." + type = list(object({ + type = string + identifiers = list(string) + })) + default = [] +} + +variable "lambda_s3_bucket" { + description = "S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly." + type = string + default = null +} + +variable "lambda_s3_key" { + description = "S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas." + type = string + default = null +} + +variable "lambda_s3_object_version" { + description = "S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket." + type = string + default = null +} + +variable "lambda_runtime" { + description = "AWS Lambda runtime." + type = string + default = "nodejs20.x" +} + +variable "lambda_architecture" { + description = "AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86_64' functions. " + type = string + default = "arm64" + validation { + condition = contains(["arm64", "x86_64"], var.lambda_architecture) + error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." + } +} + +variable "tracing_config" { + description = "Configuration for lambda tracing." + type = object({ + mode = optional(string, null) + capture_http_requests = optional(bool, false) + capture_error = optional(bool, false) + }) + default = {} +} + +# specif for this module + +variable "lambda_schedule_expression" { + description = "Scheduler expression for action runner binary syncer." + type = string + default = "rate(1 day)" +} + +variable "cleanup_config" { + description = < + ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.14.1 | -| [aws](#requirement\_aws) | ~> 4.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [null](#requirement\_null) | ~> 3.0 | ## Providers | Name | Version | |------|---------| -| [null](#provider\_null) | 3.0.0 | +| [null](#provider\_null) | 3.2.2 | ## Modules @@ -59,22 +60,4 @@ No modules. | Name | Description | |------|-------------| | [files](#output\_files) | n/a | - - -## Philips Forest - -This module is part of the Philips Forest. - -```plain - ___ _ - / __\__ _ __ ___ ___| |_ - / _\/ _ \| '__/ _ \/ __| __| - / / | (_) | | | __/\__ \ |_ - \/ \___/|_| \___||___/\__| - - Infrastructure -``` - -Talk to the forestkeepers in the `forest`-channel on Slack. - -[![Slack](https://philips-software-slackin.now.sh/badge.svg)](https://philips-software-slackin.now.sh) + \ No newline at end of file diff --git a/modules/download-lambda/outputs.tf b/modules/download-lambda/outputs.tf index 41857312fa..87a4238512 100644 --- a/modules/download-lambda/outputs.tf +++ b/modules/download-lambda/outputs.tf @@ -1,3 +1,3 @@ output "files" { - value = null_resource.download.*.triggers.file + value = null_resource.download[*].triggers.file } diff --git a/modules/download-lambda/versions.tf b/modules/download-lambda/versions.tf index ac1bb9a5d5..681964ba96 100644 --- a/modules/download-lambda/versions.tf +++ b/modules/download-lambda/versions.tf @@ -1,10 +1,14 @@ terraform { - required_version = ">= 0.14.1" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" + } + null = { + source = "hashicorp/null" + version = "~> 3.0" } } } diff --git a/modules/lambda/README.md b/modules/lambda/README.md new file mode 100644 index 0000000000..1d19920287 --- /dev/null +++ b/modules/lambda/README.md @@ -0,0 +1,49 @@ +# Module - Lambda + +> This module is treated as internal module, breaking changes will not trigger a major release bump. + +Generica module to create lambda functions + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.27 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_log_group.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.lambda_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_lambda_function.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [lambda](#input\_lambda) | Configuration for the lambda function.

`aws_partition`: Partition for the base arn if not 'aws'
`architecture`: AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions.
`environment_variables`: Environment variables for the lambda.
`handler`: The entrypoint for the lambda.
`principals`: Add extra principals to the role created for execution of the lambda, e.g. for local testing.
`lambda_tags`: Map of tags that will be added to created resources. By default resources will be tagged with name and environment.
`log_level`: Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'.
`logging_kms_key_id`: Specifies the kms key id to encrypt the logs with
`logging_retention_in_days`: Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653.
`memory_size`: Memory size linit in MB of the lambda.
`metrics_namespace`: Namespace for the metrics emitted by the lambda.
`name`: The name of the lambda function.
`prefix`: The prefix used for naming resources.
`role_path`: The path that will be added to the role, if not set the environment name will be used.
`role_permissions_boundary`: Permissions boundary that will be added to the created role for the lambda.
`runtime`: AWS Lambda runtime.
`s3_bucket`: S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly.
`s3_key`: S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas.
`s3_object_version`: S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket.
`security_group_ids`: List of security group IDs associated with the Lambda function.
`subnet_ids`: List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`.
`tags`: Map of tags that will be added to created resources. By default resources will be tagged with name and environment.
`timeout`: Time out of the lambda in seconds.
`tracing_config`: Configuration for lambda tracing.
`zip`: File location of the lambda zip file. |
object({
aws_partition = optional(string, "aws")
architecture = optional(string, "arm64")
environment_variables = optional(map(string), {})
handler = string
lambda_tags = optional(map(string), {})
log_level = optional(string, "info")
logging_kms_key_id = optional(string, null)
logging_retention_in_days = optional(number, 180)
memory_size = optional(number, 256)
metrics_namespace = optional(string, "GitHub Runners")
name = string
prefix = optional(string, null)
principals = optional(list(object({
type = string
identifiers = list(string)
})), [])
role_path = optional(string, null)
role_permissions_boundary = optional(string, null)
runtime = optional(string, "nodejs20.x")
s3_bucket = optional(string, null)
s3_key = optional(string, null)
s3_object_version = optional(string, null)
security_group_ids = optional(list(string), [])
subnet_ids = optional(list(string), [])
tags = optional(map(string), {})
timeout = optional(number, 60)
tracing_config = optional(object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
}), {})
zip = optional(string, null)
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [lambda](#output\_lambda) | n/a | + diff --git a/modules/lambda/iam.tf b/modules/lambda/iam.tf new file mode 100644 index 0000000000..d8edf747e5 --- /dev/null +++ b/modules/lambda/iam.tf @@ -0,0 +1,16 @@ +data "aws_iam_policy_document" "lambda_xray" { + count = var.lambda.tracing_config.mode != null ? 1 : 0 + statement { + actions = [ + "xray:BatchGetTraces", + "xray:GetTraceSummaries", + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ] + effect = "Allow" + resources = [ + "*" + ] + sid = "AllowXRay" + } +} diff --git a/modules/lambda/main.tf b/modules/lambda/main.tf new file mode 100644 index 0000000000..137b727774 --- /dev/null +++ b/modules/lambda/main.tf @@ -0,0 +1,112 @@ +locals { + role_path = var.lambda.role_path == null ? "/${var.lambda.prefix}/" : var.lambda.role_path + + lambda_environment_variables = { + ENVIRONMENT = var.lambda.prefix + LOG_LEVEL = var.lambda.log_level + PREFIX = var.lambda.prefix + POWERTOOLS_LOGGER_LOG_EVENT = var.lambda.log_level == "debug" ? "true" : "false" + POWERTOOLS_SERVICE_NAME = var.lambda.name + POWERTOOLS_TRACE_ENABLED = var.lambda.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.lambda.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.lambda.tracing_config.capture_error + POWERTOOLS_METRICS_NAMESPACE = var.lambda.metrics_namespace + } + + environment_variable = merge(local.lambda_environment_variables, var.lambda.environment_variables) +} + +resource "aws_lambda_function" "main" { + s3_bucket = var.lambda.s3_bucket != null ? var.lambda.s3_bucket : null + s3_key = var.lambda.s3_key != null ? var.lambda.s3_key : null + s3_object_version = var.lambda.s3_object_version != null ? var.lambda.s3_object_version : null + filename = var.lambda.s3_bucket == null ? var.lambda.zip : null + source_code_hash = var.lambda.s3_bucket == null ? filebase64sha256(var.lambda.zip) : null + function_name = "${var.lambda.prefix}-${var.lambda.name}" + role = aws_iam_role.main.arn + handler = var.lambda.handler + runtime = var.lambda.runtime + timeout = var.lambda.timeout + memory_size = var.lambda.memory_size + architectures = [var.lambda.architecture] + + environment { + variables = local.environment_variable + } + + dynamic "vpc_config" { + for_each = var.lambda.subnet_ids != null && var.lambda.security_group_ids != null ? [true] : [] + content { + security_group_ids = var.lambda.security_group_ids + subnet_ids = var.lambda.subnet_ids + } + } + + tags = merge(var.lambda.tags, var.lambda.lambda_tags) + + dynamic "tracing_config" { + for_each = var.lambda.tracing_config.mode != null ? [true] : [] + content { + mode = var.lambda.tracing_config.mode + } + } +} + +resource "aws_cloudwatch_log_group" "main" { + name = "/aws/lambda/${aws_lambda_function.main.function_name}" + retention_in_days = var.lambda.logging_retention_in_days + kms_key_id = var.lambda.logging_kms_key_id + tags = var.lambda.tags +} + +resource "aws_iam_role" "main" { + name = "${var.lambda.prefix}-${var.lambda.name}" + assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json + path = local.role_path + permissions_boundary = var.lambda.role_permissions_boundary + + tags = var.lambda.tags +} + +data "aws_iam_policy_document" "lambda_assume_role_policy" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["lambda.amazonaws.com"] + } + + dynamic "principals" { + for_each = var.lambda.principals + + content { + type = principals.value.type + identifiers = principals.value.identifiers + } + } + } +} + +resource "aws_iam_role_policy" "lambda_logging" { + name = "logging-policy" + role = aws_iam_role.main.id + + policy = templatefile("${path.module}/policies/lambda-cloudwatch.json", { + log_group_arn = aws_cloudwatch_log_group.main.arn + }) +} + +resource "aws_iam_role_policy_attachment" "vpc_execution_role" { + count = length(var.lambda.subnet_ids) > 0 ? 1 : 0 + role = aws_iam_role.main.name + policy_arn = "arn:${var.lambda.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" +} + + +resource "aws_iam_role_policy" "xray" { + count = var.lambda.tracing_config.mode != null ? 1 : 0 + name = "xray-policy" + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.main.name +} diff --git a/modules/lambda/outputs.tf b/modules/lambda/outputs.tf new file mode 100644 index 0000000000..a4704e66f9 --- /dev/null +++ b/modules/lambda/outputs.tf @@ -0,0 +1,7 @@ +output "lambda" { + value = { + function = aws_lambda_function.main + log_group = aws_cloudwatch_log_group.main + role = aws_iam_role.main + } +} diff --git a/modules/lambda/policies/lambda-cloudwatch.json b/modules/lambda/policies/lambda-cloudwatch.json new file mode 100644 index 0000000000..ad9246bcb3 --- /dev/null +++ b/modules/lambda/policies/lambda-cloudwatch.json @@ -0,0 +1,10 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["logs:CreateLogStream", "logs:PutLogEvents"], + "Resource": "${log_group_arn}*" + } + ] +} diff --git a/modules/lambda/policies/lambda-kms.json b/modules/lambda/policies/lambda-kms.json new file mode 100644 index 0000000000..63263926e5 --- /dev/null +++ b/modules/lambda/policies/lambda-kms.json @@ -0,0 +1,10 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": ["kms:GenerateDataKey", "kms:Decrypt"], + "Resource": "${kms_key_arn}" + } + ] + } \ No newline at end of file diff --git a/modules/lambda/variables.tf b/modules/lambda/variables.tf new file mode 100644 index 0000000000..549a35edda --- /dev/null +++ b/modules/lambda/variables.tf @@ -0,0 +1,88 @@ +variable "lambda" { + description = <<-EOF + Configuration for the lambda function. + + `aws_partition`: Partition for the base arn if not 'aws' + `architecture`: AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86_64' functions. + `environment_variables`: Environment variables for the lambda. + `handler`: The entrypoint for the lambda. + `principals`: Add extra principals to the role created for execution of the lambda, e.g. for local testing. + `lambda_tags`: Map of tags that will be added to created resources. By default resources will be tagged with name and environment. + `log_level`: Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. + `logging_kms_key_id`: Specifies the kms key id to encrypt the logs with + `logging_retention_in_days`: Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. + `memory_size`: Memory size linit in MB of the lambda. + `metrics_namespace`: Namespace for the metrics emitted by the lambda. + `name`: The name of the lambda function. + `prefix`: The prefix used for naming resources. + `role_path`: The path that will be added to the role, if not set the environment name will be used. + `role_permissions_boundary`: Permissions boundary that will be added to the created role for the lambda. + `runtime`: AWS Lambda runtime. + `s3_bucket`: S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. + `s3_key`: S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. + `s3_object_version`: S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. + `security_group_ids`: List of security group IDs associated with the Lambda function. + `subnet_ids`: List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. + `tags`: Map of tags that will be added to created resources. By default resources will be tagged with name and environment. + `timeout`: Time out of the lambda in seconds. + `tracing_config`: Configuration for lambda tracing. + `zip`: File location of the lambda zip file. + EOF + type = object({ + aws_partition = optional(string, "aws") + architecture = optional(string, "arm64") + environment_variables = optional(map(string), {}) + handler = string + lambda_tags = optional(map(string), {}) + log_level = optional(string, "info") + logging_kms_key_id = optional(string, null) + logging_retention_in_days = optional(number, 180) + memory_size = optional(number, 256) + metrics_namespace = optional(string, "GitHub Runners") + name = string + prefix = optional(string, null) + principals = optional(list(object({ + type = string + identifiers = list(string) + })), []) + role_path = optional(string, null) + role_permissions_boundary = optional(string, null) + runtime = optional(string, "nodejs20.x") + s3_bucket = optional(string, null) + s3_key = optional(string, null) + s3_object_version = optional(string, null) + security_group_ids = optional(list(string), []) + subnet_ids = optional(list(string), []) + tags = optional(map(string), {}) + timeout = optional(number, 60) + tracing_config = optional(object({ + mode = optional(string, null) + capture_http_requests = optional(bool, false) + capture_error = optional(bool, false) + }), {}) + zip = optional(string, null) + }) + + validation { + condition = var.lambda.zip != null || (var.lambda.s3_bucket != null && var.lambda.s3_key != null) + error_message = "Either `lambda_zip` or `lambda_s3_bucket` and `lambda_s3_key` must be provided." + } + validation { + condition = var.lambda.architecture == "arm64" || var.lambda.architecture == "x86_64" + error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." + } + validation { + condition = anytrue([ + var.lambda.log_level == "debug", + var.lambda.log_level == "info", + var.lambda.log_level == "warn", + var.lambda.log_level == "error", + ]) + error_message = "`log_level` value not valid. Valid values are 'debug', 'info', 'warn', 'error'." + + } + validation { + condition = length(var.lambda.name) + length(var.lambda.prefix) <= 63 + error_message = "The length of `name` + `prefix` must be less than or equal to 63." + } +} diff --git a/modules/lambda/versions.tf b/modules/lambda/versions.tf new file mode 100644 index 0000000000..1df1926c45 --- /dev/null +++ b/modules/lambda/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.3.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.27" + } + } +} diff --git a/modules/multi-runner/README.md b/modules/multi-runner/README.md new file mode 100644 index 0000000000..a8db4599bc --- /dev/null +++ b/modules/multi-runner/README.md @@ -0,0 +1,202 @@ +# Module - Multi runner + +> This module replaces the top-level module to make it easy to create with one deployment multiple type of runners. + +This module creates many runners with a single GitHub app. The module utilizes the internal modules and deploys parts of the stack for each runner defined. + +The module takes a configuration as input containing a matcher for the labels. The [webhook](https://philips-labs.github.io/terraform-aws-github-runner/modules/internal/webhook/) lambda is using the configuration to delegate events based on the labels in the workflow job and sent them to a dedicated queue based on the configuration. Events on each queue are processed by a dedicated lambda per configuration to scale runners. + +For each configuration: + +- When enabled, the [distribution syncer](https://philips-labs.github.io/terraform-aws-github-runner/modules/internal/runner-binaries-syncer/) is deployed for each unique combination of OS and architecture. +- For each configuration a queue is created and [runner module](https://philips-labs.github.io/terraform-aws-github-runner/modules/internal/runners/) is deployed + +## Matching + +Matching of the configuration is done based on the labels specified in labelMatchers configuration. The webhook is processing the `workflow_job` event and match the labels against the labels specified in labelMatchers configuration in the order of configuration with exact-match true first, followed by all exact matches false. + +## The catch + +Controlling which event is taken up by which runner is not to this module. It is completely done by GitHub. This means when potentially different runners can run the same job there is nothing that can be done to guarantee a certain runner will take up the job. + +An example, given you have two runners one with the labels. `self-hosted, linux, x64, large` and one with the labels `self-hosted, linux, x64, small`. Once you define a subset of the labels in the workflow, for example `self-hosted, linux, x64`. Both runners can take the job potentially. You can define to scale one of the runners for the event, but still there is no guarantee that the scaled runner takes the job. The workflow with subset of labels (`self-hosted, linux, x64`) can take up runner with specific labels (`self-hosted, linux, x64, large`) and leave the workflow with labels (`self-hosted, linux, x64, large`) be without the runner. +The only mitigation that is available right now is to use a small pool of runners. Pool instances can also exist for a short amount of time and only created once in x time based on a cron expression. + +Jobs not defining all all labels but for example only `[self-hosted, linux]` could be matched to potentially different runners. The matcher scales the first runner that matches. With the attribute `priority` the order of matchers can be defined. + +## Usages + +A complete example is available in the examples, see the [multi-runner example](https://philips-labs.github.io/terraform-aws-github-runner/examples/) for actual implementation. + +```hcl + +module "multi-runner" { + prefix = "multi-runner" + + github_app = { + # app details + } + + multi_runner_config = { + "linux-arm" = { + matcherConfig : { + labelMatchers = [["self-hosted", "linux", "arm64", "arm"]] + exactMatch = true + } + runner_config = { + runner_os = "linux" + runner_architecture = "arm64" + runner_extra_labels = "arm" + enable_ssm_on_runners = true + instance_types = ["t4g.large", "c6g.large"] + ... + } + ... + }, + "linux-x64" = { + matcherConfig : { + labelMatchers = [["self-hosted", "linux", "x64"]] + exactMatch = false + } + runner_config = { + runner_os = "linux" + runner_architecture = "x64" + instance_types = ["m5ad.large", "m5a.large"] + enable_ephemeral_runners = true + delay_webhook_event = 0 + ... + } + ... + } + } + +} +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [random](#requirement\_random) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.27 | +| [random](#provider\_random) | ~> 3.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [ami\_housekeeper](#module\_ami\_housekeeper) | ../ami-housekeeper | n/a | +| [instance\_termination\_watcher](#module\_instance\_termination\_watcher) | ../termination-watcher | n/a | +| [runner\_binaries](#module\_runner\_binaries) | ../runner-binaries-syncer | n/a | +| [runners](#module\_runners) | ../runners | n/a | +| [ssm](#module\_ssm) | ../ssm | n/a | +| [webhook](#module\_webhook) | ../webhook | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_sqs_queue.queued_builds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.queued_builds_dlq](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue.webhook_events_workflow_job_queue](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue) | resource | +| [aws_sqs_queue_policy.build_queue_dlq_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | +| [aws_sqs_queue_policy.build_queue_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | +| [aws_sqs_queue_policy.webhook_events_workflow_job_queue_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue_policy) | resource | +| [random_string.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | +| [aws_iam_policy_document.deny_unsecure_transport](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ami\_housekeeper\_cleanup\_config](#input\_ami\_housekeeper\_cleanup\_config) | Configuration for AMI cleanup. |
object({
maxItems = optional(number)
minimumDaysOld = optional(number)
amiFilters = optional(list(object({
Name = string
Values = list(string)
})))
launchTemplateNames = optional(list(string))
ssmParameterNames = optional(list(string))
dryRun = optional(bool)
})
| `{}` | no | +| [ami\_housekeeper\_lambda\_memory\_size](#input\_ami\_housekeeper\_lambda\_memory\_size) | Memory size linit in MB of the lambda. | `number` | `256` | no | +| [ami\_housekeeper\_lambda\_s3\_key](#input\_ami\_housekeeper\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [ami\_housekeeper\_lambda\_s3\_object\_version](#input\_ami\_housekeeper\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [ami\_housekeeper\_lambda\_schedule\_expression](#input\_ami\_housekeeper\_lambda\_schedule\_expression) | Scheduler expression for action runner binary syncer. | `string` | `"cron(11 7 * * ? *)"` | no | +| [ami\_housekeeper\_lambda\_timeout](#input\_ami\_housekeeper\_lambda\_timeout) | Time out of the lambda in seconds. | `number` | `300` | no | +| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | +| [associate\_public\_ipv4\_address](#input\_associate\_public\_ipv4\_address) | Associate public IPv4 with the runner. Only tested with IPv4 | `bool` | `false` | no | +| [aws\_partition](#input\_aws\_partition) | (optiona) partition in the arn namespace to use if not 'aws' | `string` | `"aws"` | no | +| [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes | +| [cloudwatch\_config](#input\_cloudwatch\_config) | (optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details. | `string` | `null` | no | +| [enable\_ami\_housekeeper](#input\_enable\_ami\_housekeeper) | Option to disable the lambda to clean up old AMIs. | `bool` | `false` | no | +| [enable\_managed\_runner\_security\_group](#input\_enable\_managed\_runner\_security\_group) | Enabling the default managed security group creation. Unmanaged security groups can be specified via `runner_additional_security_group_ids`. | `bool` | `true` | no | +| [enable\_workflow\_job\_events\_queue](#input\_enable\_workflow\_job\_events\_queue) | Enabling this experimental feature will create a secondory sqs queue to wich a copy of the workflow\_job event will be delivered. | `bool` | `false` | no | +| [ghes\_ssl\_verify](#input\_ghes\_ssl\_verify) | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | +| [ghes\_url](#input\_ghes\_url) | GitHub Enterprise Server URL. Example: https://github.internal.co - DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | +| [github\_app](#input\_github\_app) | GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
webhook_secret = string
})
| n/a | yes | +| [instance\_profile\_path](#input\_instance\_profile\_path) | The path that will be added to the instance\_profile, if not set the environment name will be used. | `string` | `null` | no | +| [instance\_termination\_watcher](#input\_instance\_termination\_watcher) | Configuration for the spot termination watcher lambda function. This feature is Beta, changes will not trigger a major release as long in beta.

`enable`: Enable or disable the spot termination watcher.
'enable\_metrics': Enable metric for the lambda. If `spot_warning` is set to true, the lambda will emit a metric when it detects a spot termination warning.
`memory_size`: Memory size linit in MB of the lambda.
`s3_key`: S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas.
`s3_object_version`: S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket.
`timeout`: Time out of the lambda in seconds.
`zip`: File location of the lambda zip file. |
object({
enable = optional(bool, false)
enable_metric = optional(object({
spot_warning = optional(bool, false)
}))
memory_size = optional(number, null)
s3_key = optional(string, null)
s3_object_version = optional(string, null)
timeout = optional(number, null)
zip = optional(string, null)
})
| `{}` | no | +| [key\_name](#input\_key\_name) | Key pair name | `string` | `null` | no | +| [kms\_key\_arn](#input\_kms\_key\_arn) | Optional CMK Key ARN to be used for Parameter Store. | `string` | `null` | no | +| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"arm64"` | no | +| [lambda\_principals](#input\_lambda\_principals) | (Optional) add extra principals to the role created for execution of the lambda, e.g. for local testing. |
list(object({
type = string
identifiers = list(string)
}))
| `[]` | no | +| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs20.x"` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `string` | `null` | no | +| [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | +| [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_tags](#input\_lambda\_tags) | Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags. | `map(string)` | `{}` | no | +| [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | +| [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with | `string` | `null` | no | +| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | +| [matcher\_config\_parameter\_store\_tier](#input\_matcher\_config\_parameter\_store\_tier) | The tier of the parameter store for the matcher configuration. Valid values are `Standard`, and `Advanced`. | `string` | `"Standard"` | no | +| [metrics\_namespace](#input\_metrics\_namespace) | The namespace for the metrics created by the module. Merics will only be created if explicit enabled. | `string` | `"GitHub Runners"` | no | +| [multi\_runner\_config](#input\_multi\_runner\_config) | multi\_runner\_config = {
runner\_config: {
runner\_os: "The EC2 Operating System type to use for action runner instances (linux,windows)."
runner\_architecture: "The platform architecture of the runner instance\_type."
runner\_metadata\_options: "(Optional) Metadata options for the ec2 runner instances."
ami\_filter: "(Optional) List of maps used to create the AMI filter for the action runner AMI. By default amazon linux 2 is used."
ami\_owners: "(Optional) The list of owners used to select the AMI of action runner instances."
create\_service\_linked\_role\_spot: (Optional) create the serviced linked role for spot instances that is required by the scale-up lambda.
credit\_specification: "(Optional) The credit specification of the runner instance\_type. Can be unset, `standard` or `unlimited`.
delay\_webhook\_event: "The number of seconds the event accepted by the webhook is invisible on the queue before the scale up lambda will receive the event."
disable\_runner\_autoupdate: "Disable the auto update of the github runner agent. Be aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/)"
ebs\_optimized: "The EC2 EBS optimized configuration."
enable\_ephemeral\_runners: "Enable ephemeral runners, runners will only be used once."
enable\_job\_queued\_check: "Enables JIT configuration for creating runners instead of registration token based registraton. JIT configuration will only be applied for ephemeral runners. By default JIT confiugration is enabled for ephemeral runners an can be disabled via this override. When running on GHES without support for JIT configuration this variable should be set to true for ephemeral runners."
enable\_runner\_on\_demand\_failover\_for\_errors "Enable on-demand failover. For example to fall back to on demand when no spot capacity is available the variable can be set to `InsufficientInstanceCapacity`. When not defined the default behavior is to retry later."
enable\_organization\_runners: "Register runners to organization, instead of repo level"
enable\_runner\_binaries\_syncer: "Option to disable the lambda to sync GitHub runner distribution, useful when using a pre-build AMI."
enable\_ssm\_on\_runners: "Enable to allow access the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances."
enable\_userdata: "Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI."
instance\_allocation\_strategy: "The allocation strategy for spot instances. AWS recommends to use `capacity-optimized` however the AWS default is `lowest-price`."
instance\_max\_spot\_price: "Max price price for spot intances per hour. This variable will be passed to the create fleet as max spot price for the fleet."
instance\_target\_capacity\_type: "Default lifecycle used for runner instances, can be either `spot` or `on-demand`."
instance\_types: "List of instance types for the action runner. Defaults are based on runner\_os (al2023 for linux and Windows Server Core for win)."
job\_queue\_retention\_in\_seconds: "The number of seconds the job is held in the queue before it is purged"
minimum\_running\_time\_in\_minutes: "The time an ec2 action runner should be running at minimum before terminated if not busy."
pool\_runner\_owner: "The pool will deploy runners to the GitHub org ID, set this value to the org to which you want the runners deployed. Repo level is not supported."
runner\_additional\_security\_group\_ids: "List of additional security groups IDs to apply to the runner. If added outside the multi\_runner\_config block, the additional security group(s) will be applied to all runner configs. If added inside the multi\_runner\_config, the additional security group(s) will be applied to the individual runner."
runner\_as\_root: "Run the action runner under the root user. Variable `runner_run_as` will be ignored."
runner\_boot\_time\_in\_minutes: "The minimum time for an EC2 runner to boot and register as a runner."
runner\_extra\_labels: "Extra (custom) labels for the runners (GitHub). Separate each label by a comma. Labels checks on the webhook can be enforced by setting `multi_runner_config.matcherConfig.exactMatch`. GitHub read-only labels should not be provided."
runner\_group\_name: "Name of the runner group."
runner\_name\_prefix: "Prefix for the GitHub runner name."
runner\_run\_as: "Run the GitHub actions agent as user."
runners\_maximum\_count: "The maximum number of runners that will be created. Setting the variable to `-1` desiables the maximum check."
scale\_down\_schedule\_expression: "Scheduler expression to check every x for scale down."
scale\_up\_reserved\_concurrent\_executions: "Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations."
userdata\_template: "Alternative user-data template, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored."
enable\_jit\_config "Overwrite the default behavior for JIT configuration. By default JIT configuration is enabled for ephemeral runners and disabled for non-ephemeral runners. In case of GHES check first if the JIT config API is avaialbe. In case you upgradeing from 3.x to 4.x you can set `enable_jit_config` to `false` to avoid a breaking change when having your own AMI."
enable\_runner\_detailed\_monitoring: "Should detailed monitoring be enabled for the runner. Set this to true if you want to use detailed monitoring. See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html for details."
enable\_cloudwatch\_agent: "Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`."
cloudwatch\_config: "(optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details."
userdata\_pre\_install: "Script to be ran before the GitHub Actions runner is installed on the EC2 instances"
userdata\_post\_install: "Script to be ran after the GitHub Actions runner is installed on the EC2 instances"
runner\_ec2\_tags: "Map of tags that will be added to the launch template instance tag specifications."
runner\_iam\_role\_managed\_policy\_arns: "Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role"
vpc\_id: "The VPC for security groups of the action runners. If not set uses the value of `var.vpc_id`."
subnet\_ids: "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. If not set, uses the value of `var.subnet_ids`."
idle\_config: "List of time period that can be defined as cron expression to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle."
runner\_log\_files: "(optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details."
block\_device\_mappings: "The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`, `snapshot_id`."
pool\_config: "The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for week days to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1."
}
matcherConfig: {
labelMatchers: "The list of list of labels supported by the runner configuration. `[[self-hosted, linux, x64, example]]`"
exactMatch: "If set to true all labels in the workflow job must match the GitHub labels (os, architecture and `self-hosted`). When false if __any__ workflow label matches it will trigger the webhook."
priority: "If set it defines the priority of the matcher, the matcher with the lowest priority will be evaluated first. Default is 999, allowed values 0-999."
}
fifo: "Enable a FIFO queue to remain the order of events received by the webhook. Suggest to set to true for repo level runners."
redrive\_build\_queue: "Set options to attach (optional) a dead letter queue to the build queue, the queue between the webhook and the scale up lambda. You have the following options. 1. Disable by setting `enabled` to false. 2. Enable by setting `enabled` to `true`, `maxReceiveCount` to a number of max retries."
} |
map(object({
runner_config = object({
runner_os = string
runner_architecture = string
runner_metadata_options = optional(map(any), {
instance_metadata_tags = "enabled"
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
})
ami_filter = optional(map(list(string)), { state = ["available"] })
ami_owners = optional(list(string), ["amazon"])
ami_id_ssm_parameter_name = optional(string, null)
ami_kms_key_arn = optional(string, "")
create_service_linked_role_spot = optional(bool, false)
credit_specification = optional(string, null)
delay_webhook_event = optional(number, 30)
disable_runner_autoupdate = optional(bool, false)
ebs_optimized = optional(bool, false)
enable_ephemeral_runners = optional(bool, false)
enable_job_queued_check = optional(bool, null)
enable_on_demand_failover_for_errors = optional(list(string), [])
enable_organization_runners = optional(bool, false)
enable_runner_binaries_syncer = optional(bool, true)
enable_ssm_on_runners = optional(bool, false)
enable_userdata = optional(bool, true)
instance_allocation_strategy = optional(string, "lowest-price")
instance_max_spot_price = optional(string, null)
instance_target_capacity_type = optional(string, "spot")
instance_types = list(string)
job_queue_retention_in_seconds = optional(number, 86400)
minimum_running_time_in_minutes = optional(number, null)
pool_runner_owner = optional(string, null)
runner_as_root = optional(bool, false)
runner_boot_time_in_minutes = optional(number, 5)
runner_extra_labels = optional(list(string), [])
runner_group_name = optional(string, "Default")
runner_name_prefix = optional(string, "")
runner_run_as = optional(string, "ec2-user")
runners_maximum_count = number
runner_additional_security_group_ids = optional(list(string), [])
scale_down_schedule_expression = optional(string, "cron(*/5 * * * ? *)")
scale_up_reserved_concurrent_executions = optional(number, 1)
userdata_template = optional(string, null)
userdata_content = optional(string, null)
enable_jit_config = optional(bool, null)
enable_runner_detailed_monitoring = optional(bool, false)
enable_cloudwatch_agent = optional(bool, true)
cloudwatch_config = optional(string, null)
userdata_pre_install = optional(string, "")
userdata_post_install = optional(string, "")
runner_ec2_tags = optional(map(string), {})
runner_iam_role_managed_policy_arns = optional(list(string), [])
vpc_id = optional(string, null)
subnet_ids = optional(list(string), null)
idle_config = optional(list(object({
cron = string
timeZone = string
idleCount = number
evictionStrategy = optional(string, "oldest_first")
})), [])
runner_log_files = optional(list(object({
log_group_name = string
prefix_log_group = bool
file_path = string
log_stream_name = string
})), null)
block_device_mappings = optional(list(object({
delete_on_termination = optional(bool, true)
device_name = optional(string, "/dev/xvda")
encrypted = optional(bool, true)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_size = number
volume_type = optional(string, "gp3")
})), [{
volume_size = 30
}])
pool_config = optional(list(object({
schedule_expression = string
size = number
})), [])
})

matcherConfig = object({
labelMatchers = list(list(string))
exactMatch = optional(bool, false)
priority = optional(number, 999)
})
fifo = optional(bool, false)
redrive_build_queue = optional(object({
enabled = bool
maxReceiveCount = number
}), {
enabled = false
maxReceiveCount = null
})
}))
| n/a | yes | +| [pool\_lambda\_reserved\_concurrent\_executions](#input\_pool\_lambda\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no | +| [pool\_lambda\_timeout](#input\_pool\_lambda\_timeout) | Time out for the pool lambda in seconds. | `number` | `60` | no | +| [prefix](#input\_prefix) | The prefix used for naming resources | `string` | `"github-actions"` | no | +| [queue\_encryption](#input\_queue\_encryption) | Configure how data on queues managed by the modules in ecrypted at REST. Options are encryped via SSE, non encrypted and via KMSS. By default encryptes via SSE is enabled. See for more details the Terraform `aws_sqs_queue` resource https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sqs_queue. |
object({
kms_data_key_reuse_period_seconds = number
kms_master_key_id = string
sqs_managed_sse_enabled = bool
})
|
{
"kms_data_key_reuse_period_seconds": null,
"kms_master_key_id": null,
"sqs_managed_sse_enabled": true
}
| no | +| [repository\_white\_list](#input\_repository\_white\_list) | List of github repository full names (owner/repo\_name) that will be allowed to use the github app. Leave empty for no filtering. | `list(string)` | `[]` | no | +| [role\_path](#input\_role\_path) | The path that will be added to the role; if not set, the environment name will be used. | `string` | `null` | no | +| [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | +| [runner\_additional\_security\_group\_ids](#input\_runner\_additional\_security\_group\_ids) | (optional) List of additional security groups IDs to apply to the runner | `list(string)` | `[]` | no | +| [runner\_binaries\_s3\_sse\_configuration](#input\_runner\_binaries\_s3\_sse\_configuration) | Map containing server-side encryption configuration for runner-binaries S3 bucket. | `any` |
{
"rule": {
"apply_server_side_encryption_by_default": {
"sse_algorithm": "AES256"
}
}
}
| no | +| [runner\_binaries\_s3\_versioning](#input\_runner\_binaries\_s3\_versioning) | Status of S3 versioning for runner-binaries S3 bucket. Once set to Enabled the change cannot be reverted via Terraform! | `string` | `"Disabled"` | no | +| [runner\_binaries\_syncer\_lambda\_timeout](#input\_runner\_binaries\_syncer\_lambda\_timeout) | Time out of the binaries sync lambda in seconds. | `number` | `300` | no | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | File location of the binaries sync lambda zip file. | `string` | `null` | no | +| [runner\_binaries\_syncer\_memory\_size](#input\_runner\_binaries\_syncer\_memory\_size) | Memory size limit in MB for binary syncer lambda. | `number` | `256` | no | +| [runner\_egress\_rules](#input\_runner\_egress\_rules) | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | +| [runners\_lambda\_s3\_key](#input\_runners\_lambda\_s3\_key) | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [runners\_lambda\_s3\_object\_version](#input\_runners\_lambda\_s3\_object\_version) | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | File location of the lambda zip file for scaling runners. | `string` | `null` | no | +| [runners\_scale\_down\_lambda\_timeout](#input\_runners\_scale\_down\_lambda\_timeout) | Time out for the scale down lambda in seconds. | `number` | `60` | no | +| [runners\_scale\_up\_lambda\_timeout](#input\_runners\_scale\_up\_lambda\_timeout) | Time out for the scale up lambda in seconds. | `number` | `30` | no | +| [runners\_ssm\_housekeeper](#input\_runners\_ssm\_housekeeper) | Configuration for the SSM housekeeper lambda. This lambda deletes token / JIT config from SSM.

`schedule_expression`: is used to configure the schedule for the lambda.
`enabled`: enable or disable the lambda trigger via the EventBridge.
`lambda_memory_size`: lambda memery size limit.
`lambda_timeout`: timeout for the lambda in seconds.
`config`: configuration for the lambda function. Token path will be read by default from the module. |
object({
schedule_expression = optional(string, "rate(1 day)")
enabled = optional(bool, true)
lambda_memory_size = optional(number, 512)
lambda_timeout = optional(number, 60)
config = object({
tokenPath = optional(string)
minimumDaysOld = optional(number, 1)
dryRun = optional(bool, false)
})
})
|
{
"config": {}
}
| no | +| [scale\_down\_lambda\_memory\_size](#input\_scale\_down\_lambda\_memory\_size) | Memory size limit in MB for scale down. | `number` | `512` | no | +| [scale\_up\_lambda\_memory\_size](#input\_scale\_up\_lambda\_memory\_size) | Memory size limit in MB for scale\_up lambda. | `number` | `512` | no | +| [ssm\_paths](#input\_ssm\_paths) | The root path used in SSM to store configuration and secreets. |
object({
root = optional(string, "github-action-runners")
app = optional(string, "app")
runners = optional(string, "runners")
webhook = optional(string, "webhook")
})
| `{}` | no | +| [state\_event\_rule\_binaries\_syncer](#input\_state\_event\_rule\_binaries\_syncer) | Option to disable EventBridge Lambda trigger for the binary syncer, useful to stop automatic updates of binary distribution | `string` | `"ENABLED"` | no | +| [subnet\_ids](#input\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | n/a | yes | +| [syncer\_lambda\_s3\_key](#input\_syncer\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [syncer\_lambda\_s3\_object\_version](#input\_syncer\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | +| [vpc\_id](#input\_vpc\_id) | The VPC for security groups of the action runners. | `string` | n/a | yes | +| [webhook\_lambda\_apigateway\_access\_log\_settings](#input\_webhook\_lambda\_apigateway\_access\_log\_settings) | Access log settings for webhook API gateway. |
object({
destination_arn = string
format = string
})
| `null` | no | +| [webhook\_lambda\_memory\_size](#input\_webhook\_lambda\_memory\_size) | Memory size limit in MB for webhook lambda. | `number` | `256` | no | +| [webhook\_lambda\_s3\_key](#input\_webhook\_lambda\_s3\_key) | S3 key for webhook lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [webhook\_lambda\_s3\_object\_version](#input\_webhook\_lambda\_s3\_object\_version) | S3 object version for webhook lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [webhook\_lambda\_timeout](#input\_webhook\_lambda\_timeout) | Time out of the lambda in seconds. | `number` | `10` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | File location of the webhook lambda zip file. | `string` | `null` | no | +| [workflow\_job\_queue\_configuration](#input\_workflow\_job\_queue\_configuration) | Configuration options for workflow job queue which is only applicable if the flag enable\_workflow\_job\_events\_queue is set to true. |
object({
delay_seconds = number
visibility_timeout_seconds = number
message_retention_seconds = number
})
|
{
"delay_seconds": null,
"message_retention_seconds": null,
"visibility_timeout_seconds": null
}
| no | + +## Outputs + +| Name | Description | +|------|-------------| +| [binaries\_syncer\_map](#output\_binaries\_syncer\_map) | n/a | +| [instance\_termination\_watcher](#output\_instance\_termination\_watcher) | n/a | +| [queues](#output\_queues) | SQS queues. | +| [runners\_map](#output\_runners\_map) | n/a | +| [ssm\_parameters](#output\_ssm\_parameters) | n/a | +| [webhook](#output\_webhook) | n/a | + diff --git a/modules/multi-runner/ami-housekeeper.tf b/modules/multi-runner/ami-housekeeper.tf new file mode 100644 index 0000000000..83ad4d49c2 --- /dev/null +++ b/modules/multi-runner/ami-housekeeper.tf @@ -0,0 +1,34 @@ + +module "ami_housekeeper" { + count = var.enable_ami_housekeeper ? 1 : 0 + source = "../ami-housekeeper" + + prefix = var.prefix + tags = local.tags + aws_partition = var.aws_partition + + lambda_zip = var.ami_housekeeper_lambda_zip + lambda_s3_bucket = var.lambda_s3_bucket + lambda_s3_key = var.ami_housekeeper_lambda_s3_key + lambda_s3_object_version = var.ami_housekeeper_lambda_s3_object_version + + lambda_architecture = var.lambda_architecture + lambda_principals = var.lambda_principals + lambda_runtime = var.lambda_runtime + lambda_security_group_ids = var.lambda_security_group_ids + lambda_subnet_ids = var.lambda_subnet_ids + lambda_memory_size = var.ami_housekeeper_lambda_memory_size + lambda_timeout = var.ami_housekeeper_lambda_timeout + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config + + logging_retention_in_days = var.logging_retention_in_days + logging_kms_key_id = var.logging_kms_key_id + log_level = var.log_level + + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + + cleanup_config = var.ami_housekeeper_cleanup_config + lambda_schedule_expression = var.ami_housekeeper_lambda_schedule_expression +} diff --git a/modules/multi-runner/main.tf b/modules/multi-runner/main.tf new file mode 100644 index 0000000000..68589248b8 --- /dev/null +++ b/modules/multi-runner/main.tf @@ -0,0 +1,25 @@ +locals { + tags = merge(var.tags, { + "ghr:environment" = var.prefix + }) + + github_app_parameters = { + id = module.ssm.parameters.github_app_id + key_base64 = module.ssm.parameters.github_app_key_base64 + } + + runner_extra_labels = { for k, v in var.multi_runner_config : k => sort(setunion(flatten(v.matcherConfig.labelMatchers), compact(v.runner_config.runner_extra_labels))) } + + runner_config = { for k, v in var.multi_runner_config : k => merge({ id = aws_sqs_queue.queued_builds[k].id, arn = aws_sqs_queue.queued_builds[k].arn }, merge(v, { runner_config = merge(v.runner_config, { runner_extra_labels = local.runner_extra_labels[k] }) })) } + + tmp_distinct_list_unique_os_and_arch = distinct([for i, config in local.runner_config : { "os_type" : config.runner_config.runner_os, "architecture" : config.runner_config.runner_architecture } if config.runner_config.enable_runner_binaries_syncer]) + unique_os_and_arch = { for i, v in local.tmp_distinct_list_unique_os_and_arch : "${v.os_type}_${v.architecture}" => v } + + ssm_root_path = "/${var.ssm_paths.root}/${var.prefix}" +} + +resource "random_string" "random" { + length = 24 + special = false + upper = false +} diff --git a/modules/multi-runner/outputs.tf b/modules/multi-runner/outputs.tf new file mode 100644 index 0000000000..47363ef35f --- /dev/null +++ b/modules/multi-runner/outputs.tf @@ -0,0 +1,61 @@ + +output "runners_map" { + value = { for runner_key, runner in module.runners : runner_key => { + launch_template_name = runner.launch_template.name + launch_template_id = runner.launch_template.id + launch_template_version = runner.launch_template.latest_version + launch_template_ami_id = runner.launch_template.image_id + lambda_up = runner.lambda_scale_up + lambda_up_log_group = runner.lambda_scale_up_log_group + lambda_down = runner.lambda_scale_down + lambda_down_log_group = runner.lambda_scale_down_log_group + lambda_pool = runner.lambda_pool + lambda_pool_log_group = runner.lambda_pool_log_group + role_runner = runner.role_runner + role_scale_up = runner.role_scale_up + role_scale_down = runner.role_scale_down + role_pool = runner.role_pool + runners_log_groups = runner.runners_log_groups + logfiles = runner.logfiles + } + } +} + +output "binaries_syncer_map" { + value = { for runner_binary_key, runner_binary in module.runner_binaries : runner_binary_key => { + lambda = runner_binary.lambda + lambda_log_group = runner_binary.lambda_log_group + lambda_role = runner_binary.lambda_role + location = "s3://runner_binary.bucket.id}/runner_binary.bucket.key" + bucket = runner_binary.bucket + } } +} + +output "webhook" { + value = { + gateway = module.webhook.gateway + lambda = module.webhook.lambda + lambda_log_group = module.webhook.lambda_log_group + lambda_role = module.webhook.role + endpoint = "${module.webhook.gateway.api_endpoint}/${module.webhook.endpoint_relative_path}" + } +} + +output "ssm_parameters" { + value = module.ssm.parameters +} + +output "queues" { + description = "SQS queues." + value = { + webhook_workflow_job_queue = try(aws_sqs_queue.webhook_events_workflow_job_queue[*].arn, "") + } +} + +output "instance_termination_watcher" { + value = var.instance_termination_watcher.enable ? { + lambda = module.instance_termination_watcher[0].lambda.function + lambda_log_group = module.instance_termination_watcher[0].lambda.log_group + lambda_role = module.instance_termination_watcher[0].lambda.role + } : null +} diff --git a/modules/multi-runner/queues.tf b/modules/multi-runner/queues.tf new file mode 100644 index 0000000000..cc53e36630 --- /dev/null +++ b/modules/multi-runner/queues.tf @@ -0,0 +1,96 @@ + +data "aws_iam_policy_document" "deny_unsecure_transport" { + statement { + sid = "DenyUnsecureTransport" + + effect = "Deny" + + principals { + type = "AWS" + identifiers = ["*"] + } + + actions = [ + "sqs:*" + ] + + resources = [ + "*" + ] + + condition { + test = "Bool" + variable = "aws:SecureTransport" + values = ["false"] + } + } +} + +resource "aws_sqs_queue" "queued_builds" { + for_each = var.multi_runner_config + name = "${var.prefix}-${each.key}-queued-builds${each.value.fifo ? ".fifo" : ""}" + delay_seconds = each.value.runner_config.delay_webhook_event + visibility_timeout_seconds = var.runners_scale_up_lambda_timeout + message_retention_seconds = each.value.runner_config.job_queue_retention_in_seconds + fifo_queue = each.value.fifo + receive_wait_time_seconds = 0 + content_based_deduplication = each.value.fifo + redrive_policy = each.value.redrive_build_queue.enabled ? jsonencode({ + deadLetterTargetArn = aws_sqs_queue.queued_builds_dlq[each.key].arn, + maxReceiveCount = each.value.redrive_build_queue.maxReceiveCount + }) : null + + sqs_managed_sse_enabled = var.queue_encryption.sqs_managed_sse_enabled + kms_master_key_id = var.queue_encryption.kms_master_key_id + kms_data_key_reuse_period_seconds = var.queue_encryption.kms_data_key_reuse_period_seconds + + tags = var.tags +} + +resource "aws_sqs_queue_policy" "build_queue_policy" { + for_each = var.multi_runner_config + queue_url = aws_sqs_queue.queued_builds[each.key].id + policy = data.aws_iam_policy_document.deny_unsecure_transport.json +} + +resource "aws_sqs_queue" "queued_builds_dlq" { + for_each = { for config, values in var.multi_runner_config : config => values if values.redrive_build_queue.enabled } + name = "${var.prefix}-${each.key}-queued-builds_dead_letter${each.value.fifo ? ".fifo" : ""}" + + sqs_managed_sse_enabled = var.queue_encryption.sqs_managed_sse_enabled + kms_master_key_id = var.queue_encryption.kms_master_key_id + kms_data_key_reuse_period_seconds = var.queue_encryption.kms_data_key_reuse_period_seconds + fifo_queue = each.value.fifo + tags = var.tags +} + +resource "aws_sqs_queue_policy" "build_queue_dlq_policy" { + for_each = { for config, values in var.multi_runner_config : config => values if values.redrive_build_queue.enabled } + queue_url = aws_sqs_queue.queued_builds_dlq[each.key].id + policy = data.aws_iam_policy_document.deny_unsecure_transport.json +} + +resource "aws_sqs_queue_policy" "webhook_events_workflow_job_queue_policy" { + count = var.enable_workflow_job_events_queue ? 1 : 0 + queue_url = aws_sqs_queue.webhook_events_workflow_job_queue[0].id + policy = data.aws_iam_policy_document.deny_unsecure_transport.json +} + +resource "aws_sqs_queue" "webhook_events_workflow_job_queue" { + count = var.enable_workflow_job_events_queue ? 1 : 0 + name = "${var.prefix}-webhook_events_workflow_job_queue" + delay_seconds = var.workflow_job_queue_configuration.delay_seconds + visibility_timeout_seconds = var.workflow_job_queue_configuration.visibility_timeout_seconds + message_retention_seconds = var.workflow_job_queue_configuration.message_retention_seconds + fifo_queue = false + receive_wait_time_seconds = 0 + content_based_deduplication = false + redrive_policy = null + + sqs_managed_sse_enabled = var.queue_encryption.sqs_managed_sse_enabled + kms_master_key_id = var.queue_encryption.kms_master_key_id + kms_data_key_reuse_period_seconds = var.queue_encryption.kms_data_key_reuse_period_seconds + + tags = var.tags +} + diff --git a/modules/multi-runner/runner-binaries.tf b/modules/multi-runner/runner-binaries.tf new file mode 100644 index 0000000000..3e20beea5a --- /dev/null +++ b/modules/multi-runner/runner-binaries.tf @@ -0,0 +1,45 @@ +module "runner_binaries" { + source = "../runner-binaries-syncer" + for_each = local.unique_os_and_arch + prefix = "${var.prefix}-${each.value.os_type}-${each.value.architecture}" + tags = local.tags + + # force mandatory lower case for s3 bucketname + distribution_bucket_name = lower("${var.prefix}-${each.value.os_type}-${each.value.architecture}-dist-${random_string.random.result}") + + runner_os = each.value.os_type + runner_architecture = each.value.architecture + + lambda_s3_bucket = var.lambda_s3_bucket + syncer_lambda_s3_key = var.syncer_lambda_s3_key + syncer_lambda_s3_object_version = var.syncer_lambda_s3_object_version + lambda_runtime = var.lambda_runtime + lambda_architecture = var.lambda_architecture + lambda_zip = var.runner_binaries_syncer_lambda_zip + lambda_memory_size = var.runner_binaries_syncer_memory_size + lambda_timeout = var.runner_binaries_syncer_lambda_timeout + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config + logging_retention_in_days = var.logging_retention_in_days + logging_kms_key_id = var.logging_kms_key_id + state_event_rule_binaries_syncer = var.state_event_rule_binaries_syncer + + server_side_encryption_configuration = var.runner_binaries_s3_sse_configuration + s3_versioning = var.runner_binaries_s3_versioning + + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + + log_level = var.log_level + + lambda_subnet_ids = var.lambda_subnet_ids + lambda_security_group_ids = var.lambda_security_group_ids + aws_partition = var.aws_partition + + lambda_principals = var.lambda_principals +} +locals { + runner_binaries_by_os_and_arch_map = { + for k, v in module.runner_binaries : k => { arn = v.bucket.arn, id = v.bucket.id, key = v.runner_distribution_object_key } + } +} diff --git a/modules/multi-runner/runners.tf b/modules/multi-runner/runners.tf new file mode 100644 index 0000000000..0c33020313 --- /dev/null +++ b/modules/multi-runner/runners.tf @@ -0,0 +1,114 @@ +module "runners" { + source = "../runners" + for_each = local.runner_config + aws_region = var.aws_region + aws_partition = var.aws_partition + vpc_id = coalesce(each.value.runner_config.vpc_id, var.vpc_id) + subnet_ids = coalesce(each.value.runner_config.subnet_ids, var.subnet_ids) + prefix = "${var.prefix}-${each.key}" + tags = merge(local.tags, { + "ghr:environment" = "${var.prefix}-${each.key}" + }) + + s3_runner_binaries = each.value.runner_config.enable_runner_binaries_syncer ? local.runner_binaries_by_os_and_arch_map["${each.value.runner_config.runner_os}_${each.value.runner_config.runner_architecture}"] : null + + ssm_paths = { + root = "${local.ssm_root_path}/${each.key}" + tokens = "${var.ssm_paths.runners}/tokens" + config = "${var.ssm_paths.runners}/config" + } + + runner_os = each.value.runner_config.runner_os + instance_types = each.value.runner_config.instance_types + instance_target_capacity_type = each.value.runner_config.instance_target_capacity_type + instance_allocation_strategy = each.value.runner_config.instance_allocation_strategy + instance_max_spot_price = each.value.runner_config.instance_max_spot_price + block_device_mappings = each.value.runner_config.block_device_mappings + + runner_architecture = each.value.runner_config.runner_architecture + ami_filter = each.value.runner_config.ami_filter + ami_owners = each.value.runner_config.ami_owners + ami_id_ssm_parameter_name = each.value.runner_config.ami_id_ssm_parameter_name + ami_kms_key_arn = each.value.runner_config.ami_kms_key_arn + + sqs_build_queue = { "arn" : each.value.arn } + github_app_parameters = local.github_app_parameters + ebs_optimized = each.value.runner_config.ebs_optimized + enable_on_demand_failover_for_errors = each.value.runner_config.enable_on_demand_failover_for_errors + enable_organization_runners = each.value.runner_config.enable_organization_runners + enable_ephemeral_runners = each.value.runner_config.enable_ephemeral_runners + enable_jit_config = each.value.runner_config.enable_jit_config + enable_job_queued_check = each.value.runner_config.enable_job_queued_check + disable_runner_autoupdate = each.value.runner_config.disable_runner_autoupdate + enable_managed_runner_security_group = var.enable_managed_runner_security_group + enable_runner_detailed_monitoring = each.value.runner_config.enable_runner_detailed_monitoring + scale_down_schedule_expression = each.value.runner_config.scale_down_schedule_expression + minimum_running_time_in_minutes = each.value.runner_config.minimum_running_time_in_minutes + runner_boot_time_in_minutes = each.value.runner_config.runner_boot_time_in_minutes + runner_labels = sort(distinct(concat(["self-hosted", each.value.runner_config.runner_os, each.value.runner_config.runner_architecture], each.value.runner_config.runner_extra_labels))) + runner_as_root = each.value.runner_config.runner_as_root + runner_run_as = each.value.runner_config.runner_run_as + runners_maximum_count = each.value.runner_config.runners_maximum_count + idle_config = each.value.runner_config.idle_config + enable_ssm_on_runners = each.value.runner_config.enable_ssm_on_runners + egress_rules = var.runner_egress_rules + runner_additional_security_group_ids = try(coalescelist(each.value.runner_config.runner_additional_security_group_ids, var.runner_additional_security_group_ids), []) + metadata_options = each.value.runner_config.runner_metadata_options + credit_specification = each.value.runner_config.credit_specification + + enable_runner_binaries_syncer = each.value.runner_config.enable_runner_binaries_syncer + lambda_s3_bucket = var.lambda_s3_bucket + runners_lambda_s3_key = var.runners_lambda_s3_key + runners_lambda_s3_object_version = var.runners_lambda_s3_object_version + lambda_runtime = var.lambda_runtime + lambda_architecture = var.lambda_architecture + lambda_zip = var.runners_lambda_zip + lambda_scale_up_memory_size = var.scale_up_lambda_memory_size + lambda_timeout_scale_up = var.runners_scale_up_lambda_timeout + lambda_scale_down_memory_size = var.scale_down_lambda_memory_size + lambda_timeout_scale_down = var.runners_scale_down_lambda_timeout + lambda_subnet_ids = var.lambda_subnet_ids + lambda_security_group_ids = var.lambda_security_group_ids + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config + logging_retention_in_days = var.logging_retention_in_days + logging_kms_key_id = var.logging_kms_key_id + enable_cloudwatch_agent = each.value.runner_config.enable_cloudwatch_agent + cloudwatch_config = try(coalesce(each.value.runner_config.cloudwatch_config, var.cloudwatch_config), null) + runner_log_files = each.value.runner_config.runner_log_files + runner_group_name = each.value.runner_config.runner_group_name + runner_name_prefix = each.value.runner_config.runner_name_prefix + + scale_up_reserved_concurrent_executions = each.value.runner_config.scale_up_reserved_concurrent_executions + + instance_profile_path = var.instance_profile_path + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + + enable_userdata = each.value.runner_config.enable_userdata + userdata_template = each.value.runner_config.userdata_template + userdata_content = each.value.runner_config.userdata_content + userdata_pre_install = each.value.runner_config.userdata_pre_install + userdata_post_install = each.value.runner_config.userdata_post_install + key_name = var.key_name + runner_ec2_tags = each.value.runner_config.runner_ec2_tags + + create_service_linked_role_spot = each.value.runner_config.create_service_linked_role_spot + + runner_iam_role_managed_policy_arns = each.value.runner_config.runner_iam_role_managed_policy_arns + + ghes_url = var.ghes_url + ghes_ssl_verify = var.ghes_ssl_verify + + kms_key_arn = var.kms_key_arn + + log_level = var.log_level + + pool_config = each.value.runner_config.pool_config + pool_lambda_timeout = var.pool_lambda_timeout + pool_runner_owner = each.value.runner_config.pool_runner_owner + pool_lambda_reserved_concurrent_executions = var.pool_lambda_reserved_concurrent_executions + associate_public_ipv4_address = var.associate_public_ipv4_address + + ssm_housekeeper = var.runners_ssm_housekeeper +} diff --git a/modules/multi-runner/ssm.tf b/modules/multi-runner/ssm.tf new file mode 100644 index 0000000000..6b2591f465 --- /dev/null +++ b/modules/multi-runner/ssm.tf @@ -0,0 +1,8 @@ +module "ssm" { + source = "../ssm" + + kms_key_arn = var.kms_key_arn + path_prefix = "${local.ssm_root_path}/${var.ssm_paths.app}" + github_app = var.github_app + tags = local.tags +} diff --git a/modules/multi-runner/termination-watcher.tf b/modules/multi-runner/termination-watcher.tf new file mode 100644 index 0000000000..8481c50399 --- /dev/null +++ b/modules/multi-runner/termination-watcher.tf @@ -0,0 +1,28 @@ +locals { + lambda_instance_termination_watcher = { + prefix = var.prefix + tags = local.tags + aws_partition = var.aws_partition + architecture = var.lambda_architecture + principals = var.lambda_principals + runtime = var.lambda_runtime + security_group_ids = var.lambda_security_group_ids + subnet_ids = var.lambda_subnet_ids + log_level = var.log_level + logging_kms_key_id = var.logging_kms_key_id + logging_retention_in_days = var.logging_retention_in_days + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + metrics_namespace = var.metrics_namespace + s3_bucket = var.lambda_s3_bucket + tracing_config = var.tracing_config + lambda_tags = var.lambda_tags + } +} + +module "instance_termination_watcher" { + source = "../termination-watcher" + count = var.instance_termination_watcher.enable ? 1 : 0 + + config = merge(local.lambda_instance_termination_watcher, var.instance_termination_watcher) +} diff --git a/modules/multi-runner/variables.ami-housekeepr.tf b/modules/multi-runner/variables.ami-housekeepr.tf new file mode 100644 index 0000000000..f92211b6c0 --- /dev/null +++ b/modules/multi-runner/variables.ami-housekeepr.tf @@ -0,0 +1,58 @@ + +variable "enable_ami_housekeeper" { + description = "Option to disable the lambda to clean up old AMIs." + type = bool + default = false +} + +variable "ami_housekeeper_lambda_zip" { + description = "File location of the lambda zip file." + type = string + default = null +} + +variable "ami_housekeeper_lambda_memory_size" { + description = "Memory size linit in MB of the lambda." + type = number + default = 256 +} + +variable "ami_housekeeper_lambda_timeout" { + description = "Time out of the lambda in seconds." + type = number + default = 300 +} + +variable "ami_housekeeper_lambda_s3_key" { + description = "S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas." + type = string + default = null +} + +variable "ami_housekeeper_lambda_s3_object_version" { + description = "S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket." + type = string + default = null +} + +variable "ami_housekeeper_lambda_schedule_expression" { + description = "Scheduler expression for action runner binary syncer." + type = string + default = "cron(11 7 * * ? *)" # once a day +} + +variable "ami_housekeeper_cleanup_config" { + description = "Configuration for AMI cleanup." + type = object({ + maxItems = optional(number) + minimumDaysOld = optional(number) + amiFilters = optional(list(object({ + Name = string + Values = list(string) + }))) + launchTemplateNames = optional(list(string)) + ssmParameterNames = optional(list(string)) + dryRun = optional(bool) + }) + default = {} +} diff --git a/modules/multi-runner/variables.tf b/modules/multi-runner/variables.tf new file mode 100644 index 0000000000..b44731f382 --- /dev/null +++ b/modules/multi-runner/variables.tf @@ -0,0 +1,662 @@ +variable "github_app" { + description = "GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`)." + type = object({ + key_base64 = string + id = string + webhook_secret = string + }) +} + +variable "prefix" { + description = "The prefix used for naming resources" + type = string + default = "github-actions" +} + +variable "kms_key_arn" { + description = "Optional CMK Key ARN to be used for Parameter Store." + type = string + default = null +} + +variable "tags" { + description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." + type = map(string) + default = {} +} + +variable "multi_runner_config" { + type = map(object({ + runner_config = object({ + runner_os = string + runner_architecture = string + runner_metadata_options = optional(map(any), { + instance_metadata_tags = "enabled" + http_endpoint = "enabled" + http_tokens = "required" + http_put_response_hop_limit = 1 + }) + ami_filter = optional(map(list(string)), { state = ["available"] }) + ami_owners = optional(list(string), ["amazon"]) + ami_id_ssm_parameter_name = optional(string, null) + ami_kms_key_arn = optional(string, "") + create_service_linked_role_spot = optional(bool, false) + credit_specification = optional(string, null) + delay_webhook_event = optional(number, 30) + disable_runner_autoupdate = optional(bool, false) + ebs_optimized = optional(bool, false) + enable_ephemeral_runners = optional(bool, false) + enable_job_queued_check = optional(bool, null) + enable_on_demand_failover_for_errors = optional(list(string), []) + enable_organization_runners = optional(bool, false) + enable_runner_binaries_syncer = optional(bool, true) + enable_ssm_on_runners = optional(bool, false) + enable_userdata = optional(bool, true) + instance_allocation_strategy = optional(string, "lowest-price") + instance_max_spot_price = optional(string, null) + instance_target_capacity_type = optional(string, "spot") + instance_types = list(string) + job_queue_retention_in_seconds = optional(number, 86400) + minimum_running_time_in_minutes = optional(number, null) + pool_runner_owner = optional(string, null) + runner_as_root = optional(bool, false) + runner_boot_time_in_minutes = optional(number, 5) + runner_extra_labels = optional(list(string), []) + runner_group_name = optional(string, "Default") + runner_name_prefix = optional(string, "") + runner_run_as = optional(string, "ec2-user") + runners_maximum_count = number + runner_additional_security_group_ids = optional(list(string), []) + scale_down_schedule_expression = optional(string, "cron(*/5 * * * ? *)") + scale_up_reserved_concurrent_executions = optional(number, 1) + userdata_template = optional(string, null) + userdata_content = optional(string, null) + enable_jit_config = optional(bool, null) + enable_runner_detailed_monitoring = optional(bool, false) + enable_cloudwatch_agent = optional(bool, true) + cloudwatch_config = optional(string, null) + userdata_pre_install = optional(string, "") + userdata_post_install = optional(string, "") + runner_ec2_tags = optional(map(string), {}) + runner_iam_role_managed_policy_arns = optional(list(string), []) + vpc_id = optional(string, null) + subnet_ids = optional(list(string), null) + idle_config = optional(list(object({ + cron = string + timeZone = string + idleCount = number + evictionStrategy = optional(string, "oldest_first") + })), []) + runner_log_files = optional(list(object({ + log_group_name = string + prefix_log_group = bool + file_path = string + log_stream_name = string + })), null) + block_device_mappings = optional(list(object({ + delete_on_termination = optional(bool, true) + device_name = optional(string, "/dev/xvda") + encrypted = optional(bool, true) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) + volume_size = number + volume_type = optional(string, "gp3") + })), [{ + volume_size = 30 + }]) + pool_config = optional(list(object({ + schedule_expression = string + size = number + })), []) + }) + + matcherConfig = object({ + labelMatchers = list(list(string)) + exactMatch = optional(bool, false) + priority = optional(number, 999) + }) + fifo = optional(bool, false) + redrive_build_queue = optional(object({ + enabled = bool + maxReceiveCount = number + }), { + enabled = false + maxReceiveCount = null + }) + })) + description = < 0 ? aws_sqs_queue.webhook_events_workflow_job_queue[0] : null + + github_app_parameters = { + webhook_secret = module.ssm.parameters.github_app_webhook_secret + } + + lambda_s3_bucket = var.lambda_s3_bucket + webhook_lambda_s3_key = var.webhook_lambda_s3_key + webhook_lambda_s3_object_version = var.webhook_lambda_s3_object_version + webhook_lambda_apigateway_access_log_settings = var.webhook_lambda_apigateway_access_log_settings + lambda_runtime = var.lambda_runtime + lambda_architecture = var.lambda_architecture + lambda_zip = var.webhook_lambda_zip + lambda_timeout = var.webhook_lambda_timeout + lambda_memory_size = var.webhook_lambda_memory_size + lambda_tags = var.lambda_tags + tracing_config = var.tracing_config + logging_retention_in_days = var.logging_retention_in_days + logging_kms_key_id = var.logging_kms_key_id + + role_path = var.role_path + role_permissions_boundary = var.role_permissions_boundary + repository_white_list = var.repository_white_list + + lambda_subnet_ids = var.lambda_subnet_ids + lambda_security_group_ids = var.lambda_security_group_ids + aws_partition = var.aws_partition + + log_level = var.log_level +} diff --git a/modules/runner-binaries-syncer/README.md b/modules/runner-binaries-syncer/README.md index a5bb294e28..ef6eb10606 100644 --- a/modules/runner-binaries-syncer/README.md +++ b/modules/runner-binaries-syncer/README.md @@ -1,10 +1,8 @@ # Module - Runner binaries syncer -This module creates a lambda that will sync GitHub action binary to a S3 bucket, the lambda will be triggered via a CloudWatch event. The distribution is cached to avoid the latency of downloading the distribution during the setup. After deployment the lambda will be triggered via an S3 object created at deployment time. - -## Usages +> This module is treated as internal module, breaking changes will not trigger a major release bump. -Usage examples are available in the root module. By default the root module will assume local zip files containing the lambda distribution are available. See the [download lambda module](../download-lambda/README.md) for more information. +This module creates a lambda that will sync GitHub action binary to a S3 bucket, the lambda will be triggered via a CloudWatch event. The distribution is cached to avoid the latency of downloading the distribution during the setup. After deployment the lambda will be triggered via an S3 object created at deployment time. ## Lambda Function @@ -33,19 +31,19 @@ To compile all TypeScript/JavaScript sources in a single file [ncc](https://gith yarn run dist ``` - + ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.14.1 | -| [aws](#requirement\_aws) | ~> 4.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | ~> 4.0 | +| [aws](#provider\_aws) | ~> 5.27 | ## Modules @@ -62,54 +60,60 @@ No modules. | [aws_iam_role_policy.lambda_kms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.lambda_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.syncer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.syncer_lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.syncer_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_lambda_function.syncer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | | [aws_lambda_permission.on_deploy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.syncer](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_s3_bucket.action_dist](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | -| [aws_s3_bucket_acl.action_dist_acl](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_acl) | resource | -| [aws_s3_bucket_lifecycle_configuration.bucket-config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | +| [aws_s3_bucket_lifecycle_configuration.bucket_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) | resource | | [aws_s3_bucket_logging.action_dist_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_logging) | resource | | [aws_s3_bucket_notification.on_deploy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_notification) | resource | -| [aws_s3_bucket_policy.action_dist_sse_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | +| [aws_s3_bucket_ownership_controls.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | +| [aws_s3_bucket_policy.action_dist_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | | [aws_s3_bucket_public_access_block.action_dist](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | | [aws_s3_bucket_server_side_encryption_configuration.action_dist](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration) | resource | +| [aws_s3_bucket_versioning.action_dist](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning) | resource | | [aws_s3_object.trigger](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object) | resource | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_iam_policy_document.action_dist_sse_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.action_dist_bucket_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes | +| [aws\_partition](#input\_aws\_partition) | (optional) partition for the base arn if not 'aws' | `string` | `"aws"` | no | | [distribution\_bucket\_name](#input\_distribution\_bucket\_name) | Bucket for storing the action runner distribution. | `string` | n/a | yes | -| [environment](#input\_environment) | A name that identifies the environment, used as prefix and for tagging. | `string` | `null` | no | -| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"x86_64"` | no | +| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"arm64"` | no | +| [lambda\_memory\_size](#input\_lambda\_memory\_size) | Memory size of the lambda. | `number` | `256` | no | | [lambda\_principals](#input\_lambda\_principals) | (Optional) add extra principals to the role created for execution of the lambda, e.g. for local testing. |
list(object({
type = string
identifiers = list(string)
}))
| `[]` | no | -| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs16.x"` | no | -| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | +| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs20.x"` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `string` | `null` | no | | [lambda\_schedule\_expression](#input\_lambda\_schedule\_expression) | Scheduler expression for action runner binary syncer. | `string` | `"cron(27 * * * ? *)"` | no | | [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | | [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_tags](#input\_lambda\_tags) | Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags. | `map(string)` | `{}` | no | | [lambda\_timeout](#input\_lambda\_timeout) | Time out of the lambda in seconds. | `number` | `300` | no | | [lambda\_zip](#input\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | | [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | -| [log\_type](#input\_log\_type) | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with | `string` | `null` | no | -| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `7` | no | +| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | | [prefix](#input\_prefix) | The prefix used for naming resources | `string` | `"github-actions"` | no | | [role\_path](#input\_role\_path) | The path that will be added to the role, if not set the environment name will be used. | `string` | `null` | no | | [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | -| [runner\_allow\_prerelease\_binaries](#input\_runner\_allow\_prerelease\_binaries) | (Deprecated, no longer used), allow the runners to update to prerelease binaries. | `bool` | `null` | no | | [runner\_architecture](#input\_runner\_architecture) | The platform architecture of the runner instance\_type. | `string` | `"x64"` | no | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux,windows). | `string` | `"linux"` | no | | [s3\_logging\_bucket](#input\_s3\_logging\_bucket) | Bucket for action runner distribution bucket access logging. | `string` | `null` | no | | [s3\_logging\_bucket\_prefix](#input\_s3\_logging\_bucket\_prefix) | Bucket prefix for action runner distribution bucket access logging. | `string` | `null` | no | -| [server\_side\_encryption\_configuration](#input\_server\_side\_encryption\_configuration) | Map containing server-side encryption configuration. | `any` | `{}` | no | -| [syncer\_lambda\_s3\_key](#input\_syncer\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| [syncer\_lambda\_s3\_object\_version](#input\_syncer\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | +| [s3\_versioning](#input\_s3\_versioning) | Status of S3 versioning for runner-binaries S3 bucket. | `string` | `"Disabled"` | no | +| [server\_side\_encryption\_configuration](#input\_server\_side\_encryption\_configuration) | Map containing server-side encryption configuration for runner-binaries S3 bucket. | `any` |
{
"rule": {
"apply_server_side_encryption_by_default": {
"sse_algorithm": "AES256"
}
}
}
| no | +| [state\_event\_rule\_binaries\_syncer](#input\_state\_event\_rule\_binaries\_syncer) | Option to disable EventBridge Lambda trigger for the binary syncer, useful to stop automatic updates of binary distribution | `string` | `"ENABLED"` | no | +| [syncer\_lambda\_s3\_key](#input\_syncer\_lambda\_s3\_key) | S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [syncer\_lambda\_s3\_object\_version](#input\_syncer\_lambda\_s3\_object\_version) | S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | | [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | ## Outputs @@ -117,24 +121,7 @@ No modules. |------|-------------| | [bucket](#output\_bucket) | n/a | | [lambda](#output\_lambda) | n/a | +| [lambda\_log\_group](#output\_lambda\_log\_group) | n/a | | [lambda\_role](#output\_lambda\_role) | n/a | | [runner\_distribution\_object\_key](#output\_runner\_distribution\_object\_key) | n/a | - - -## Philips Forest - -This module is part of the Philips Forest. - -```plain - ___ _ - / __\__ _ __ ___ ___| |_ - / _\/ _ \| '__/ _ \/ __| __| - / / | (_) | | | __/\__ \ |_ - \/ \___/|_| \___||___/\__| - - Infrastructure -``` - -Talk to the forestkeepers in the `forest`-channel on Slack. - -[![Slack](https://philips-software-slackin.now.sh/badge.svg)](https://philips-software-slackin.now.sh) + diff --git a/modules/runner-binaries-syncer/iam.tf b/modules/runner-binaries-syncer/iam.tf new file mode 100644 index 0000000000..454d943b4b --- /dev/null +++ b/modules/runner-binaries-syncer/iam.tf @@ -0,0 +1,16 @@ +data "aws_iam_policy_document" "lambda_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + statement { + actions = [ + "xray:BatchGetTraces", + "xray:GetTraceSummaries", + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ] + effect = "Allow" + resources = [ + "*" + ] + sid = "AllowXRay" + } +} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.nvmrc b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.nvmrc deleted file mode 100644 index 5edcff0364..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v16 \ No newline at end of file diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/README.md b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/README.md deleted file mode 100644 index a6efc59623..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Lambda runner binary syncer - -For testing the lambda locally check out [this guide](../../../../docs/test-lambda-local.md). \ No newline at end of file diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json deleted file mode 100644 index 8fd4203576..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "github-runner-lambda-syncer", - "version": "1.0.0", - "main": "lambda.ts", - "license": "MIT", - "scripts": { - "start": "ts-node-dev src/local.ts", - "test": "NODE_ENV=test jest", - "test:watch": "NODE_ENV=test jest --watch", - "lint": "yarn eslint src", - "watch": "ts-node-dev --respawn --exit-child src/local.ts", - "build": "ncc build src/lambda.ts -o dist", - "dist": "yarn build && cd dist && zip ../runner-binaries-syncer.zip index.js", - "format": "prettier --write \"**/*.ts\"", - "format-check": "prettier --check \"**/*.ts\"", - "all": "yarn build && yarn format && yarn lint && yarn test" - }, - "devDependencies": { - "@octokit/rest": "^19.0.5", - "@trivago/prettier-plugin-sort-imports": "^4.0.0", - "@types/jest": "^29.2.4", - "@types/node": "^18.11.18", - "@types/request": "^2.48.8", - "@typescript-eslint/eslint-plugin": "^5.47.1", - "@typescript-eslint/parser": "^5.47.1", - "@vercel/ncc": "^0.36.0", - "eslint": "^8.30.0", - "eslint-plugin-prettier": "4.2.1", - "jest": "^29.3", - "jest-mock": "^29.3.1", - "prettier": "2.8.1", - "ts-jest": "^29.0.3", - "ts-node-dev": "^2.0.0", - "typescript": "^4.9.4" - }, - "dependencies": { - "axios": "^1.2.1", - "aws-sdk": "^2.1283.0", - "tslog": "^3.3.4" - } -} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts deleted file mode 100644 index 1c73c705bc..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/lambda.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { logger } from './syncer/logger'; -import { sync } from './syncer/syncer'; - -// eslint-disable-next-line -export async function handler(event: any, context: any): Promise { - logger.setSettings({ requestId: context.awsRequestId }); - logger.debug(JSON.stringify(event)); - - try { - await sync(); - } catch (e) { - if (e instanceof Error) { - logger.warn(`Ignoring error: ${e.message}`); - } - logger.trace(e); - } -} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts deleted file mode 100644 index 47670fe2cf..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/logger.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Logger } from 'tslog'; - -export type LogType = 'json' | 'pretty' | 'hidden'; -export type LogLevel = 'silly' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; - -export const logger = new Logger({ - colorizePrettyLogs: false, - displayInstanceName: false, - minLevel: (process.env.LOG_LEVEL as LogLevel) || 'info', - name: 'runner-binaries-syncer', - overwriteConsole: true, - type: (process.env.LOG_TYPE as LogType) || 'pretty', -}); diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts deleted file mode 100644 index 07fa1bc852..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/src/syncer/modules.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LogLevel, LogType } from './logger'; - -declare namespace NodeJS { - export interface ProcessEnv { - LOG_LEVEL: LogLevel; - LOG_TYPE: LogType; - } -} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json deleted file mode 100644 index 764f2f6ae0..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/tsconfig.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "compilerOptions": { - /* Basic Options */ - "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, - "outDir": "build", - "lib": [ - "es2020", - "DOM" - ] /* Specify library files to be included in the compilation. */, - "allowJs": true /* Allow javascript files to be compiled. */, - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "./", /* Redirect output structure to the directory. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "incremental": true, /* Enable incremental compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - /* Module Resolution Options */ - "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [] /* List of folders to include type definitions from. */, - // "types": [] /* Type declaration files to be included in compilation. */, - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - /* Experimental Options */ - "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, - "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "resolveJsonModule": true, - "sourceMap": true - }, - "include": [ - "src/**/*" - ] -} diff --git a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock b/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock deleted file mode 100644 index 6edcfad33e..0000000000 --- a/modules/runner-binaries-syncer/lambdas/runner-binaries-syncer/yarn.lock +++ /dev/null @@ -1,4022 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== - dependencies: - "@babel/highlight" "^7.16.0" - -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/compat-data@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" - integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== - -"@babel/compat-data@^7.19.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.4.tgz#95c86de137bf0317f3a570e1b6e996b427299747" - integrity sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw== - -"@babel/core@7.17.8": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.8.tgz#3dac27c190ebc3a4381110d46c80e77efe172e1a" - integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.7" - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.8" - "@babel/parser" "^7.17.8" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c" - integrity sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.3" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-module-transforms" "^7.19.0" - "@babel/helpers" "^7.19.0" - "@babel/parser" "^7.19.3" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.3" - "@babel/types" "^7.19.3" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad" - integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.17.3", "@babel/generator@^7.17.7", "@babel/generator@^7.19.3", "@babel/generator@^7.19.4", "@babel/generator@^7.7.2": - version "7.19.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.5.tgz#da3f4b301c8086717eee9cab14da91b1fa5dcca7" - integrity sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg== - dependencies: - "@babel/types" "^7.19.4" - "@jridgewell/gen-mapping" "^0.3.2" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.17.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" - integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== - dependencies: - "@babel/compat-data" "^7.18.8" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz#a10a04588125675d7c7ae299af86fa1b2ee038ca" - integrity sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg== - dependencies: - "@babel/compat-data" "^7.19.3" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== - dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.17.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" - integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-module-transforms@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" - integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-plugin-utils@^7.18.6": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" - integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== - -"@babel/helper-simple-access@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" - integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helpers@^7.17.8": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" - integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== - dependencies: - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helpers@^7.19.0": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.4.tgz#42154945f87b8148df7203a25c31ba9a73be46c5" - integrity sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.4" - "@babel/types" "^7.19.4" - -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" - integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539" - integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg== - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.0", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.17.8", "@babel/parser@^7.18.10", "@babel/parser@^7.18.6", "@babel/parser@^7.19.3", "@babel/parser@^7.19.4": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.0.tgz#b26133c888da4d79b0d3edcf42677bcadc783046" - integrity sha512-G9VgAhEaICnz8iiJeGJQyVl6J2nTjbW0xeisva0PK6XcKsga7BIaqm4ZF8Rg1Wbaqmy6znspNqhPaPkyukujzg== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz#2feeb13d9334cc582ea9111d3506f773174179bb" - integrity sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/template@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" - integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/template@^7.3.3": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" - integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/traverse@7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.17.3", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.3", "@babel/traverse@^7.19.4", "@babel/traverse@^7.7.2": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.4.tgz#f117820e18b1e59448a6c1fa9d0ff08f7ac459a8" - integrity sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.4" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.19.4" - "@babel/types" "^7.19.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.3", "@babel/types@^7.19.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7" - integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw== - dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@eslint/eslintrc@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" - integrity sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.3.1.tgz#3e3f876e4e47616ea3b1464b9fbda981872e9583" - integrity sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - -"@jest/core@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.3.1.tgz#bff00f413ff0128f4debec1099ba7dcd649774a1" - integrity sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/reporters" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.2.0" - jest-config "^29.3.1" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-resolve-dependencies "^29.3.1" - jest-runner "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - jest-watcher "^29.3.1" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.3.1.tgz#eb039f726d5fcd14698acd072ac6576d41cfcaa6" - integrity sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag== - dependencies: - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-mock "^29.3.1" - -"@jest/expect-utils@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.3.1.tgz#531f737039e9b9e27c42449798acb5bba01935b6" - integrity sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g== - dependencies: - jest-get-type "^29.2.0" - -"@jest/expect@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.3.1.tgz#456385b62894349c1d196f2d183e3716d4c6a6cd" - integrity sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg== - dependencies: - expect "^29.3.1" - jest-snapshot "^29.3.1" - -"@jest/fake-timers@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.3.1.tgz#b140625095b60a44de820876d4c14da1aa963f67" - integrity sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A== - dependencies: - "@jest/types" "^29.3.1" - "@sinonjs/fake-timers" "^9.1.2" - "@types/node" "*" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -"@jest/globals@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.3.1.tgz#92be078228e82d629df40c3656d45328f134a0c6" - integrity sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/types" "^29.3.1" - jest-mock "^29.3.1" - -"@jest/reporters@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.3.1.tgz#9a6d78c109608e677c25ddb34f907b90e07b4310" - integrity sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - jest-worker "^29.3.1" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.0.0": - version "29.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" - integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== - dependencies: - "@sinclair/typebox" "^0.24.1" - -"@jest/source-map@^29.2.0": - version "29.2.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" - integrity sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.3.1.tgz#92cd5099aa94be947560a24610aa76606de78f50" - integrity sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz#fa24b3b050f7a59d48f7ef9e0b782ab65123090d" - integrity sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA== - dependencies: - "@jest/test-result" "^29.3.1" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - slash "^3.0.0" - -"@jest/transform@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.3.1.tgz#1e6bd3da4af50b5c82a539b7b1f3770568d6e36d" - integrity sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.1" - -"@jest/types@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" - integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== - dependencies: - "@jest/schemas" "^29.0.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@octokit/auth-token@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.0.tgz#6f22c5fc56445c496628488ba6810131558fa4a9" - integrity sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ== - dependencies: - "@octokit/types" "^6.0.3" - -"@octokit/core@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.1.0.tgz#b6b03a478f1716de92b3f4ec4fd64d05ba5a9251" - integrity sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ== - dependencies: - "@octokit/auth-token" "^3.0.0" - "@octokit/graphql" "^5.0.0" - "@octokit/request" "^6.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^8.0.0" - before-after-hook "^2.2.0" - universal-user-agent "^6.0.0" - -"@octokit/endpoint@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.0.tgz#be758a1236d68d6bbb505e686dd50881c327a519" - integrity sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ== - dependencies: - "@octokit/types" "^6.0.3" - is-plain-object "^5.0.0" - universal-user-agent "^6.0.0" - -"@octokit/graphql@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.0.tgz#2cc6eb3bf8e0278656df1a7d0ca0d7591599e3b3" - integrity sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ== - dependencies: - "@octokit/request" "^6.0.0" - "@octokit/types" "^6.0.3" - universal-user-agent "^6.0.0" - -"@octokit/openapi-types@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" - integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== - -"@octokit/openapi-types@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a" - integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw== - -"@octokit/plugin-paginate-rest@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz#93d7e74f1f69d68ba554fa6b888c2a9cf1f99a83" - integrity sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw== - dependencies: - "@octokit/types" "^8.0.0" - -"@octokit/plugin-request-log@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" - integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== - -"@octokit/plugin-rest-endpoint-methods@^6.7.0": - version "6.7.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz#2f6f17f25b6babbc8b41d2bb0a95a8839672ce7c" - integrity sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw== - dependencies: - "@octokit/types" "^8.0.0" - deprecation "^2.3.1" - -"@octokit/request-error@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.0.tgz#f527d178f115a3b62d76ce4804dd5bdbc0270a81" - integrity sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w== - dependencies: - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.1.0.tgz#80bdac78dff583a8fa0978baeda139a71d98d10c" - integrity sha512-36V+sP4bJli31TRq8sea3d/Q1XGgZ9cnqpsegkLCnvpu+hoYephSkxGlWg4KB6dyUM1IWPXVrLFOKYzObQ+MZg== - dependencies: - "@octokit/endpoint" "^7.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^6.16.1" - is-plain-object "^5.0.0" - node-fetch "^2.6.7" - universal-user-agent "^6.0.0" - -"@octokit/rest@^19.0.5": - version "19.0.5" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.5.tgz#4dbde8ae69b27dca04b5f1d8119d282575818f6c" - integrity sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow== - dependencies: - "@octokit/core" "^4.1.0" - "@octokit/plugin-paginate-rest" "^5.0.0" - "@octokit/plugin-request-log" "^1.0.4" - "@octokit/plugin-rest-endpoint-methods" "^6.7.0" - -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1": - version "6.34.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218" - integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== - dependencies: - "@octokit/openapi-types" "^11.2.0" - -"@octokit/types@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.0.0.tgz#93f0b865786c4153f0f6924da067fe0bb7426a9f" - integrity sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg== - dependencies: - "@octokit/openapi-types" "^14.0.0" - -"@sinclair/typebox@^0.24.1": - version "0.24.20" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.20.tgz#11a657875de6008622d53f56e063a6347c51a6dd" - integrity sha512-kVaO5aEFZb33nPMTZBxiPEkY+slxiPtqC7QX8f9B3eGOMBvEfuMfxp9DSTTCsRJPumPKjrge4yagyssO4q6qzQ== - -"@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^9.1.2": - version "9.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" - integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== - dependencies: - "@sinonjs/commons" "^1.7.0" - -"@trivago/prettier-plugin-sort-imports@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.0.0.tgz#e0936d87fb8d65865c857e6a6dba644103db1b30" - integrity sha512-Tyuk5ZY4a0e2MNFLdluQO9F6d1awFQYXVVujEPFfvKPPXz8DADNHzz73NMhwCSXGSuGGZcA/rKOyZBrxVNMxaA== - dependencies: - "@babel/core" "7.17.8" - "@babel/generator" "7.17.7" - "@babel/parser" "7.18.9" - "@babel/traverse" "7.17.3" - "@babel/types" "7.17.0" - javascript-natural-sort "0.7.1" - lodash "4.17.21" - -"@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== - -"@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== - -"@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== - -"@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== - -"@types/babel__core@^7.1.14": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" - integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" - integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" - integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== - dependencies: - "@babel/types" "^7.3.0" - -"@types/caseless@*": - version "0.12.2" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" - integrity sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w== - -"@types/graceful-fs@^4.1.3": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^29.2.4": - version "29.2.4" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.2.4.tgz#9c155c4b81c9570dbd183eb8604aa0ae80ba5a5b" - integrity sha512-PipFB04k2qTRPePduVLTRiPzQfvMeLwUN3Z21hsAKaB/W9IIzgB2pizCL466ftJlcyZqnHoC9ZHpxLGl3fS86A== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - -"@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/node@*": - version "18.11.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.12.tgz#89e7f8aa8c88abf432f9bd594888144d7dba10aa" - integrity sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg== - -"@types/node@^18.11.18": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== - -"@types/prettier@^2.1.5": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.2.tgz#4c62fae93eb479660c3bd93f9d24d561597a8281" - integrity sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA== - -"@types/request@^2.48.8": - version "2.48.8" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.8.tgz#0b90fde3b655ab50976cb8c5ac00faca22f5a82c" - integrity sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ== - dependencies: - "@types/caseless" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - form-data "^2.5.0" - -"@types/semver@^7.3.12": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== - -"@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== - -"@types/strip-bom@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" - integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= - -"@types/strip-json-comments@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" - integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== - -"@types/tough-cookie@*": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.1.tgz#8f80dd965ad81f3e1bc26d6f5c727e132721ff40" - integrity sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg== - -"@types/yargs-parser@*": - version "20.2.1" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" - integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== - -"@types/yargs@^17.0.8": - version "17.0.10" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a" - integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz#50cc5085578a7fa22cd46a0806c2e5eae858af02" - integrity sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/type-utils" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.1.tgz#c4bf16f8c3c7608ce4bf8ff804b677fc899f173f" - integrity sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz#0d302b3c2f20ab24e4787bf3f5a0d8c449b823bd" - integrity sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - -"@typescript-eslint/type-utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz#aee13314f840ab336c1adb49a300856fd16d04ce" - integrity sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w== - dependencies: - "@typescript-eslint/typescript-estree" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.1.tgz#459f07428aec5a8c4113706293c2ae876741ac8e" - integrity sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A== - -"@typescript-eslint/typescript-estree@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz#b9d8441308aca53df7f69b2c67a887b82c9ed418" - integrity sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.1.tgz#595f25ac06e9ee28c339fd43c709402820b13d7b" - integrity sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw== - dependencies: - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz#d35c2da544dbb685db9c5b5b85adac0a1d74d1f2" - integrity sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig== - dependencies: - "@typescript-eslint/types" "5.47.1" - eslint-visitor-keys "^3.3.0" - -"@vercel/ncc@^0.36.0": - version "0.36.0" - resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.36.0.tgz#1f262b86fc4f0770bbc0fc1d331d5aaa1bd47334" - integrity sha512-/ZTUJ/ZkRt694k7KJNimgmHjtQcRuVwsST2Z6XfYveQIuBbHR+EqkTc1jfgPkQmMyk/vtpxo3nVxe8CNuau86A== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== - -acorn@^8.8.0: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -aws-sdk@^2.1283.0: - version "2.1283.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1283.0.tgz#87dafacd3e4c9dd89f5de0bce43cafb50fd5c9e4" - integrity sha512-YlxTF0T9X8AcNrOzFPVOPnX1jNtHZjYHRUCfpsVwqdajHDGGruVsVppgBYXEiCRuTQNUhcJTUx0J0uKBhKQZIA== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.4.19" - -axios@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.1.tgz#44cf04a3c9f0c2252ebd85975361c026cb9f864a" - integrity sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -babel-jest@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.3.1.tgz#05c83e0d128cd48c453eea851482a38782249f44" - integrity sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA== - dependencies: - "@jest/transform" "^29.3.1" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.2.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz#23ee99c37390a98cfddf3ef4a78674180d823094" - integrity sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" - integrity sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA== - dependencies: - babel-plugin-jest-hoist "^29.2.0" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.20.2: - version "4.21.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf" - integrity sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA== - dependencies: - caniuse-lite "^1.0.30001366" - electron-to-chromium "^1.4.188" - node-releases "^2.0.6" - update-browserslist-db "^1.0.4" - -browserslist@^4.21.3: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== - dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" - -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" - integrity sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA== - -caniuse-lite@^1.0.30001366: - version "1.0.30001367" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz#2b97fe472e8fa29c78c5970615d7cd2ee414108a" - integrity sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw== - -caniuse-lite@^1.0.30001400: - version "1.0.30001420" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001420.tgz#f62f35f051e0b6d25532cf376776d41e45b47ef6" - integrity sha512-OnyeJ9ascFA9roEj72ok2Ikp7PHJTKubtEJIQ/VK3fdsS50q4KWy+Z5X0A1/GswEItKX0ctAp8n4SYDE7wTu6A== - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -ci-info@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" - integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== - -cjs-module-lexer@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" - integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -combined-stream@^1.0.6, combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "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://registry.yarnpkg.com/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" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -diff-sequences@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" - integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dynamic-dedupe@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" - integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= - dependencies: - xtend "^4.0.0" - -electron-to-chromium@^1.4.188: - version "1.4.192" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.192.tgz#fac050058b3e0713b401a1088cc579e14c2ab165" - integrity sha512-8nCXyIQY9An88NXAp+PuPy5h3/w5ZY7Iu2lag65Q0XREprcat5F8gKhoHsBUnQcFuCRnmevpR8yEBYRU3d2HDw== - -electron-to-chromium@^1.4.251: - version "1.4.283" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.283.tgz#d4f263f5df402fd799c0a06255d580dcf8aa9a8e" - integrity sha512-g6RQ9zCOV+U5QVHW9OpFR7rdk/V7xfopNXnyAamdpFgCHgZ1sjI8VuR1+zG2YG/TZk+tQ8mpNkug4P8FU0fuOA== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0: - version "1.20.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-plugin-prettier@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^8.30.0: - version "8.30.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" - integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== - dependencies: - "@eslint/eslintrc" "^1.4.0" - "@humanwhocodes/config-array" "^0.11.8" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expect@^29.0.0, expect@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.3.1.tgz#92877aad3f7deefc2e3f6430dd195b92295554a6" - integrity sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA== - dependencies: - "@jest/expect-utils" "^29.3.1" - jest-get-type "^29.2.0" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== - dependencies: - bser "2.1.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== - -follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -form-data@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^7.1.3, glob@^7.1.4: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.19.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" - integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c" - integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.3.tgz#4d51c2c495ca9393da259ec66b62e022920211e0" - integrity sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-core-module@^2.2.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" - integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" - for-each "^0.3.3" - has-tostringtag "^1.0.0" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" - integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" - integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -javascript-natural-sort@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" - integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= - -jest-changed-files@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289" - integrity sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA== - dependencies: - execa "^5.0.0" - p-limit "^3.1.0" - -jest-circus@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.3.1.tgz#177d07c5c0beae8ef2937a67de68f1e17bbf1b4a" - integrity sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - p-limit "^3.1.0" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.3.1.tgz#e89dff427db3b1df50cea9a393ebd8640790416d" - integrity sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ== - dependencies: - "@jest/core" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-config@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.3.1.tgz#0bc3dcb0959ff8662957f1259947aedaefb7f3c6" - integrity sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.3.1" - "@jest/types" "^29.3.1" - babel-jest "^29.3.1" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.3.1" - jest-environment-node "^29.3.1" - jest-get-type "^29.2.0" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-runner "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" - integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-docblock@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" - integrity sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.3.1.tgz#bc375c8734f1bb96625d83d1ca03ef508379e132" - integrity sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA== - dependencies: - "@jest/types" "^29.3.1" - chalk "^4.0.0" - jest-get-type "^29.2.0" - jest-util "^29.3.1" - pretty-format "^29.3.1" - -jest-environment-node@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.3.1.tgz#5023b32472b3fba91db5c799a0d5624ad4803e74" - integrity sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -jest-get-type@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" - integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== - -jest-haste-map@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.3.1.tgz#af83b4347f1dae5ee8c2fb57368dc0bb3e5af843" - integrity sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A== - dependencies: - "@jest/types" "^29.3.1" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - jest-worker "^29.3.1" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz#95336d020170671db0ee166b75cd8ef647265518" - integrity sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA== - dependencies: - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-matcher-utils@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572" - integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ== - dependencies: - chalk "^4.0.0" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-message-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" - integrity sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.3.1" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.3.1.tgz#60287d92e5010979d01f218c6b215b688e0f313e" - integrity sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-util "^29.3.1" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" - integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== - -jest-resolve-dependencies@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz#a6a329708a128e68d67c49f38678a4a4a914c3bf" - integrity sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA== - dependencies: - jest-regex-util "^29.2.0" - jest-snapshot "^29.3.1" - -jest-resolve@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.3.1.tgz#9a4b6b65387a3141e4a40815535c7f196f1a68a7" - integrity sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-pnp-resolver "^1.2.2" - jest-util "^29.3.1" - jest-validate "^29.3.1" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" - -jest-runner@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.3.1.tgz#a92a879a47dd096fea46bb1517b0a99418ee9e2d" - integrity sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA== - dependencies: - "@jest/console" "^29.3.1" - "@jest/environment" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.2.0" - jest-environment-node "^29.3.1" - jest-haste-map "^29.3.1" - jest-leak-detector "^29.3.1" - jest-message-util "^29.3.1" - jest-resolve "^29.3.1" - jest-runtime "^29.3.1" - jest-util "^29.3.1" - jest-watcher "^29.3.1" - jest-worker "^29.3.1" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.3.1.tgz#21efccb1a66911d6d8591276a6182f520b86737a" - integrity sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/globals" "^29.3.1" - "@jest/source-map" "^29.2.0" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.3.1.tgz#17bcef71a453adc059a18a32ccbd594b8cc4e45e" - integrity sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.3.1" - graceful-fs "^4.2.9" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - jest-haste-map "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - natural-compare "^1.4.0" - pretty-format "^29.3.1" - semver "^7.3.5" - -jest-util@^29.0.0, jest-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" - integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.3.1.tgz#d56fefaa2e7d1fde3ecdc973c7f7f8f25eea704a" - integrity sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g== - dependencies: - "@jest/types" "^29.3.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.2.0" - leven "^3.1.0" - pretty-format "^29.3.1" - -jest-watcher@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.3.1.tgz#3341547e14fe3c0f79f9c3a4c62dbc3fc977fd4a" - integrity sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg== - dependencies: - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.3.1" - string-length "^4.0.1" - -jest-worker@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" - integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== - dependencies: - "@types/node" "*" - jest-util "^29.3.1" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.3: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.3.1.tgz#c130c0d551ae6b5459b8963747fed392ddbde122" - integrity sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA== - dependencies: - "@jest/core" "^29.3.1" - "@jest/types" "^29.3.1" - import-local "^3.0.2" - jest-cli "^29.3.1" - -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - -js-sdsl@^4.1.4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" - integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash@4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -make-error@1.x, make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-types@^2.1.12: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.5, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - 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" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -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= - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -pirates@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" - integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" - integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== - -pretty-format@^29.0.0, pretty-format@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" - integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== - dependencies: - "@jest/schemas" "^29.0.0" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== - -resolve@^1.0.0, resolve@^1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= - -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@7.x, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.7: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - -signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@^0.5.12, source-map-support@^0.5.21: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== - dependencies: - escape-string-regexp "^2.0.0" - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-jest@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" - integrity sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.1" - lodash.memoize "4.x" - make-error "1.x" - semver "7.x" - yargs-parser "^21.0.1" - -ts-node-dev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" - integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== - dependencies: - chokidar "^3.5.1" - dynamic-dedupe "^0.3.0" - minimist "^1.2.6" - mkdirp "^1.0.4" - resolve "^1.0.0" - rimraf "^2.6.1" - source-map-support "^0.5.12" - tree-kill "^1.2.2" - ts-node "^10.4.0" - tsconfig "^7.0.0" - -ts-node@^10.4.0: - version "10.8.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.1.tgz#ea2bd3459011b52699d7e88daa55a45a1af4f066" - integrity sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" - integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== - dependencies: - "@types/strip-bom" "^3.0.0" - "@types/strip-json-comments" "0.0.30" - strip-bom "^3.0.0" - strip-json-comments "^2.0.0" - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslog@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.3.4.tgz#083197a908c97b3b714a0576b9dac293f223f368" - integrity sha512-N0HHuHE0e/o75ALfkioFObknHR5dVchUad4F0XyFf3gXJYB++DewEzwGI/uIOM216E5a43ovnRNEeQIq9qgm4Q== - dependencies: - source-map-support "^0.5.21" - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -typescript@^4.9.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== - -update-browserslist-db@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" - integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -update-browserslist-db@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -util@^0.12.4: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -v8-to-istanbul@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" - integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" - integrity sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" - for-each "^0.3.3" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.9" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.0.0, yargs-parser@^21.0.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c" - integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/modules/runner-binaries-syncer/main.tf b/modules/runner-binaries-syncer/main.tf index e431a877b2..4e8c9febca 100644 --- a/modules/runner-binaries-syncer/main.tf +++ b/modules/runner-binaries-syncer/main.tf @@ -8,12 +8,14 @@ resource "aws_s3_bucket" "action_dist" { tags = var.tags } -resource "aws_s3_bucket_acl" "action_dist_acl" { +resource "aws_s3_bucket_ownership_controls" "this" { bucket = aws_s3_bucket.action_dist.id - acl = "private" + rule { + object_ownership = "BucketOwnerEnforced" + } } -resource "aws_s3_bucket_lifecycle_configuration" "bucket-config" { +resource "aws_s3_bucket_lifecycle_configuration" "bucket_config" { bucket = aws_s3_bucket.action_dist.id rule { @@ -70,38 +72,59 @@ resource "aws_s3_bucket_logging" "action_dist_logging" { target_prefix = var.s3_logging_bucket_prefix != null ? var.s3_logging_bucket_prefix : var.distribution_bucket_name } -data "aws_iam_policy_document" "action_dist_sse_policy" { - count = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default, null) != null ? 1 : 0 +resource "aws_s3_bucket_versioning" "action_dist" { + bucket = aws_s3_bucket.action_dist.id + versioning_configuration { + status = var.s3_versioning + } +} +data "aws_iam_policy_document" "action_dist_bucket_policy" { statement { - effect = "Deny" + sid = "ForceSSLOnlyAccess" + effect = "Deny" + actions = ["s3:*"] + resources = [aws_s3_bucket.action_dist.arn, "${aws_s3_bucket.action_dist.arn}/*"] principals { - type = "AWS" + identifiers = ["*"] + type = "*" + } - identifiers = [ - "*", - ] + condition { + test = "Bool" + values = ["false"] + variable = "aws:SecureTransport" } + } + + dynamic "statement" { + for_each = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default, null) != null ? [true] : [] - actions = [ - "s3:PutObject", - ] + content { + sid = "ForceSSE" + effect = "Deny" + actions = ["s3:PutObject"] + resources = ["${aws_s3_bucket.action_dist.arn}/*"] - resources = [ - "${aws_s3_bucket.action_dist.arn}/*", - ] + principals { + type = "AWS" - condition { - test = "StringNotEquals" - variable = "s3:x-amz-server-side-encryption" - values = [var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm] + identifiers = [ + "*", + ] + } + + condition { + test = "StringNotEquals" + variable = "s3:x-amz-server-side-encryption" + values = [var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm] + } } } } -resource "aws_s3_bucket_policy" "action_dist_sse_policy" { - count = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default, null) != null ? 1 : 0 +resource "aws_s3_bucket_policy" "action_dist_bucket_policy" { bucket = aws_s3_bucket.action_dist.id - policy = data.aws_iam_policy_document.action_dist_sse_policy[0].json + policy = data.aws_iam_policy_document.action_dist_bucket_policy.json } diff --git a/modules/runner-binaries-syncer/outputs.tf b/modules/runner-binaries-syncer/outputs.tf index 6d46d82e26..09dd0ad58f 100644 --- a/modules/runner-binaries-syncer/outputs.tf +++ b/modules/runner-binaries-syncer/outputs.tf @@ -10,6 +10,10 @@ output "lambda" { value = aws_lambda_function.syncer } +output "lambda_log_group" { + value = aws_cloudwatch_log_group.syncer +} + output "lambda_role" { value = aws_iam_role.syncer_lambda } diff --git a/modules/runner-binaries-syncer/runner-binaries-syncer.tf b/modules/runner-binaries-syncer/runner-binaries-syncer.tf index 8bd0330af4..6be75c3332 100644 --- a/modules/runner-binaries-syncer/runner-binaries-syncer.tf +++ b/modules/runner-binaries-syncer/runner-binaries-syncer.tf @@ -1,5 +1,5 @@ locals { - lambda_zip = var.lambda_zip == null ? "${path.module}/lambdas/runner-binaries-syncer/runner-binaries-syncer.zip" : var.lambda_zip + lambda_zip = var.lambda_zip == null ? "${path.module}/../../lambdas/functions/gh-agent-syncer/runner-binaries-syncer.zip" : var.lambda_zip role_path = var.role_path == null ? "/${var.prefix}/" : var.role_path gh_binary_os_label = { windows = "win", @@ -18,19 +18,23 @@ resource "aws_lambda_function" "syncer" { handler = "index.handler" runtime = var.lambda_runtime timeout = var.lambda_timeout - memory_size = 256 + memory_size = var.lambda_memory_size architectures = [var.lambda_architecture] environment { variables = { - GITHUB_RUNNER_ARCHITECTURE = var.runner_architecture - GITHUB_RUNNER_OS = local.gh_binary_os_label[var.runner_os] - LOG_LEVEL = var.log_level - LOG_TYPE = var.log_type - S3_BUCKET_NAME = aws_s3_bucket.action_dist.id - S3_OBJECT_KEY = local.action_runner_distribution_object_key - S3_SSE_ALGORITHM = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm, null) - S3_SSE_KMS_KEY_ID = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.kms_master_key_id, null) + ENVIRONMENT = var.prefix + GITHUB_RUNNER_ARCHITECTURE = var.runner_architecture + GITHUB_RUNNER_OS = local.gh_binary_os_label[var.runner_os] + LOG_LEVEL = var.log_level + POWERTOOLS_LOGGER_LOG_EVENT = var.log_level == "debug" ? "true" : "false" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error + S3_BUCKET_NAME = aws_s3_bucket.action_dist.id + S3_OBJECT_KEY = local.action_runner_distribution_object_key + S3_SSE_ALGORITHM = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.sse_algorithm, null) + S3_SSE_KMS_KEY_ID = try(var.server_side_encryption_configuration.rule.apply_server_side_encryption_by_default.kms_master_key_id, null) } } @@ -42,7 +46,14 @@ resource "aws_lambda_function" "syncer" { } } - tags = var.tags + tags = merge(var.tags, var.lambda_tags) + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } } resource "aws_iam_role_policy" "lambda_kms" { @@ -100,14 +111,6 @@ resource "aws_iam_role_policy" "lambda_logging" { }) } -resource "aws_iam_role_policy" "lambda_syncer_vpc" { - count = length(var.lambda_subnet_ids) > 0 && length(var.lambda_security_group_ids) > 0 ? 1 : 0 - name = "${var.prefix}-lambda-syncer-vpc" - role = aws_iam_role.syncer_lambda.id - - policy = file("${path.module}/policies/lambda-vpc.json") -} - resource "aws_iam_role_policy" "syncer" { name = "${var.prefix}-lambda-syncer-s3-policy" role = aws_iam_role.syncer_lambda.id @@ -121,6 +124,7 @@ resource "aws_cloudwatch_event_rule" "syncer" { name = "${var.prefix}-syncer-rule" schedule_expression = var.lambda_schedule_expression tags = var.tags + state = var.state_event_rule_binaries_syncer } resource "aws_cloudwatch_event_target" "syncer" { @@ -128,6 +132,12 @@ resource "aws_cloudwatch_event_target" "syncer" { arn = aws_lambda_function.syncer.arn } +resource "aws_iam_role_policy_attachment" "syncer_vpc_execution_role" { + count = length(var.lambda_subnet_ids) > 0 ? 1 : 0 + role = aws_iam_role.syncer_lambda.name + policy_arn = "arn:${var.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" +} + resource "aws_lambda_permission" "syncer" { statement_id = "AllowExecutionFromCloudWatch" action = "lambda:InvokeFunction" @@ -173,3 +183,9 @@ resource "aws_lambda_permission" "on_deploy" { source_account = data.aws_caller_identity.current.account_id source_arn = aws_s3_bucket.action_dist.arn } + +resource "aws_iam_role_policy" "syncer_lambda_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.syncer_lambda.name +} diff --git a/modules/runner-binaries-syncer/variables.tf b/modules/runner-binaries-syncer/variables.tf index 0c59811e75..b8c8643706 100644 --- a/modules/runner-binaries-syncer/variables.tf +++ b/modules/runner-binaries-syncer/variables.tf @@ -1,25 +1,9 @@ -variable "aws_region" { - description = "AWS region." - type = string -} - variable "tags" { description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." type = map(string) default = {} } -variable "environment" { - description = "A name that identifies the environment, used as prefix and for tagging." - type = string - default = null - - validation { - condition = var.environment == null - error_message = "The \"environment\" variable is no longer used. To migrate, set the \"prefix\" variable to the original value of \"environment\" and optionally, add \"Environment\" to the \"tags\" variable map with the same value." - } -} - variable "prefix" { description = "The prefix used for naming resources" type = string @@ -54,10 +38,21 @@ variable "s3_logging_bucket_prefix" { type = string default = null - # Make sure the bucket name only contains legal characters + # Make sure the bucket prefix only contains legal characters validation { - error_message = "Only lowercase alphanumeric characters and hyphens allowed in the bucket name." - condition = var.s3_logging_bucket_prefix == null || can(regex("^[a-z0-9-]*$", var.s3_logging_bucket_prefix)) + error_message = "Only alphanumeric characters, hyphens followed by single slashes allowed in the bucket prefix." + condition = var.s3_logging_bucket_prefix == null || can(regex("^(([a-zA-Z0-9-])+(\\/?))*$", var.s3_logging_bucket_prefix)) + } +} + +variable "state_event_rule_binaries_syncer" { + type = string + description = "Option to disable EventBridge Lambda trigger for the binary syncer, useful to stop automatic updates of binary distribution" + default = "ENABLED" + + validation { + condition = contains(["ENABLED", "DISABLED", "ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS"], var.state_event_rule_binaries_syncer) + error_message = "`state_event_rule_binaries_syncer` value is not valid, valid values are: `ENABLED`, `DISABLED`, `ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS`." } } @@ -79,6 +74,12 @@ variable "lambda_timeout" { default = 300 } +variable "lambda_memory_size" { + description = "Memory size of the lambda." + type = number + default = 256 +} + variable "role_permissions_boundary" { description = "Permissions boundary that will be added to the created role for the lambda." type = string @@ -118,7 +119,7 @@ variable "runner_architecture" { variable "logging_retention_in_days" { description = "Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653." type = number - default = 7 + default = 180 } variable "logging_kms_key_id" { @@ -127,29 +128,21 @@ variable "logging_kms_key_id" { default = null } -variable "runner_allow_prerelease_binaries" { - description = "(Deprecated, no longer used), allow the runners to update to prerelease binaries." - type = bool - default = null - - validation { - condition = var.runner_allow_prerelease_binaries == null - error_message = "The \"runner_allow_prerelease_binaries\" variable is no longer used. GitHub runners are not released as pre-release, only releases should be used." - } -} - variable "lambda_s3_bucket" { description = "S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly." + type = string default = null } variable "syncer_lambda_s3_key" { description = "S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas." + type = string default = null } variable "syncer_lambda_s3_object_version" { description = "S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket." + type = string default = null } @@ -165,18 +158,10 @@ variable "lambda_security_group_ids" { default = [] } -variable "log_type" { - description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " +variable "aws_partition" { + description = "(optional) partition for the base arn if not 'aws'" type = string - default = "pretty" - validation { - condition = anytrue([ - var.log_type == "json", - var.log_type == "pretty", - var.log_type == "hidden", - ]) - error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." - } + default = "aws" } variable "log_level" { @@ -185,22 +170,36 @@ variable "log_level" { default = "info" validation { condition = anytrue([ - var.log_level == "silly", - var.log_level == "trace", var.log_level == "debug", var.log_level == "info", var.log_level == "warn", var.log_level == "error", - var.log_level == "fatal", ]) - error_message = "`log_level` value not valid. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + error_message = "`log_level` value not valid. Valid values are 'debug', 'info', 'warn', 'error'." + } + validation { + condition = !contains(["silly", "trace", "fatal"], var.log_level) + error_message = "PLEASE MIGRATE: The following log levels: 'silly', 'trace' and 'fatal' are not longer supported." } + } variable "server_side_encryption_configuration" { - description = "Map containing server-side encryption configuration." + description = "Map containing server-side encryption configuration for runner-binaries S3 bucket." type = any - default = {} + default = { + rule = { + apply_server_side_encryption_by_default = { + sse_algorithm = "AES256" + } + } + } +} + +variable "s3_versioning" { + description = "Status of S3 versioning for runner-binaries S3 bucket." + type = string + default = "Disabled" } variable "lambda_principals" { @@ -215,15 +214,31 @@ variable "lambda_principals" { variable "lambda_runtime" { description = "AWS Lambda runtime." type = string - default = "nodejs16.x" + default = "nodejs20.x" } variable "lambda_architecture" { description = "AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86_64' functions. " type = string - default = "x86_64" + default = "arm64" validation { condition = contains(["arm64", "x86_64"], var.lambda_architecture) error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." } } + +variable "tracing_config" { + description = "Configuration for lambda tracing." + type = object({ + mode = optional(string, null) + capture_http_requests = optional(bool, false) + capture_error = optional(bool, false) + }) + default = {} +} + +variable "lambda_tags" { + description = "Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags." + type = map(string) + default = {} +} diff --git a/modules/runner-binaries-syncer/versions.tf b/modules/runner-binaries-syncer/versions.tf index ac1bb9a5d5..1df1926c45 100644 --- a/modules/runner-binaries-syncer/versions.tf +++ b/modules/runner-binaries-syncer/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.14.1" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } } } diff --git a/modules/runners/README.md b/modules/runners/README.md index b2e8fd0a55..35dbf1fa73 100644 --- a/modules/runners/README.md +++ b/modules/runners/README.md @@ -1,5 +1,7 @@ # Module - Scale runners +> This module is treated as internal module, breaking changes will not trigger a major release bump. + This module creates resources required to run the GitHub action runner on AWS EC2 spot instances. The life cycle of the runners on AWS is managed by two lambda functions. One function will handle scaling up, the other scaling down. ## Overview @@ -16,10 +18,6 @@ The scale up lambda is triggered by events on a SQS queue. Events on this queue The scale down lambda is triggered via a CloudWatch event. The event is triggered by a cron expression defined in the variable `scale_down_schedule_expression` (https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html). For scaling down GitHub does not provide a good API yet, therefore we run the scaling down based on this event every x minutes. Each time the lambda is triggered it tries to remove all runners older than x minutes (configurable) managed in this deployment. In case the runner can be removed from GitHub, which means it is not executing a workflow, the lambda will terminate the EC2 instance. -## Usages - -Usage examples are available in the root module. By default the root module will assume local zip files containing the lambda distribution are available. See the [download lambda module](../download-lambda/README.md) for more information. - ## Lambda Function The Lambda function is written in [TypeScript](https://www.typescriptlang.org/) and requires Node 12.x and yarn. Sources are located in [./lambdas/runners]. Two lambda functions share the same sources, there is one entry point for `scaleDown` and another one for `scaleUp`. @@ -47,19 +45,19 @@ To compile all TypeScript/JavaScript sources in a single file [ncc](https://gith yarn run dist ``` - + ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.14.1 | -| [aws](#requirement\_aws) | ~> 4.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | ~> 4.0 | +| [aws](#provider\_aws) | ~> 5.27 | ## Modules @@ -72,14 +70,19 @@ yarn run dist | Name | Type | |------|------| | [aws_cloudwatch_event_rule.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_rule.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_target.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_event_target.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_log_group.gh_runners](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_cloudwatch_log_group.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_iam_instance_profile.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_policy.ami_id_ssm_parameter_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource | | [aws_iam_role.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.describe_tags](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.dist_bucket](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | @@ -87,81 +90,101 @@ yarn run dist | [aws_iam_role_policy.runner_session_manager_aws_managed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.scale_down_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.scale_down_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.scale_up_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.scale_up_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.service_linked_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.ssm_housekeeper_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.ssm_housekeeper_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.ssm_parameters](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.ami_id_ssm_parameter_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.managed_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.scale_down_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_iam_role_policy_attachment.scale_up_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.ssm_housekeeper_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.xray_tracing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_lambda_event_source_mapping.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_event_source_mapping) | resource | | [aws_lambda_function.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | | [aws_lambda_function.scale_up](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_function.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | | [aws_lambda_permission.scale_down](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_lambda_permission.scale_runners_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_lambda_permission.ssm_housekeeper](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_launch_template.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | | [aws_security_group.runner_sg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | | [aws_ssm_parameter.cloudwatch_agent_config_runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.jit_config_enabled](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | | [aws_ssm_parameter.runner_agent_mode](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | | [aws_ssm_parameter.runner_config_run_as](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | | [aws_ssm_parameter.runner_enable_cloudwatch](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.token_path](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | | [aws_ami.runner](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami\_filter](#input\_ami\_filter) | Map of lists used to create the AMI filter for the action runner AMI. | `map(list(string))` | `null` | no | +| [ami\_filter](#input\_ami\_filter) | Map of lists used to create the AMI filter for the action runner AMI. | `map(list(string))` |
{
"state": [
"available"
]
}
| no | +| [ami\_id\_ssm\_parameter\_name](#input\_ami\_id\_ssm\_parameter\_name) | Externally managed SSM parameter (of data type aws:ec2:image) that contains the AMI ID to launch runner instances from. Overrides ami\_filter | `string` | `null` | no | +| [ami\_kms\_key\_arn](#input\_ami\_kms\_key\_arn) | Optional CMK Key ARN to be used to launch an instance from a shared encrypted AMI | `string` | `null` | no | | [ami\_owners](#input\_ami\_owners) | The list of owners used to select the AMI of action runner instances. | `list(string)` |
[
"amazon"
]
| no | +| [associate\_public\_ipv4\_address](#input\_associate\_public\_ipv4\_address) | Associate public IPv4 with the runner. Only tested with IPv4 | `bool` | `false` | no | | [aws\_partition](#input\_aws\_partition) | (optional) partition for the base arn if not 'aws' | `string` | `"aws"` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes | -| [block\_device\_mappings](#input\_block\_device\_mappings) | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`, `snapshot_id`. |
list(object({
delete_on_termination = bool
device_name = string
encrypted = bool
iops = number
kms_key_id = string
snapshot_id = string
throughput = number
volume_size = number
volume_type = string
}))
|
[
{
"delete_on_termination": true,
"device_name": "/dev/xvda",
"encrypted": true,
"iops": null,
"kms_key_id": null,
"snapshot_id": null,
"throughput": null,
"volume_size": 30,
"volume_type": "gp3"
}
]
| no | +| [block\_device\_mappings](#input\_block\_device\_mappings) | The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`, `snapshot_id`. |
list(object({
delete_on_termination = optional(bool, true)
device_name = optional(string, "/dev/xvda")
encrypted = optional(bool, true)
iops = optional(number)
kms_key_id = optional(string)
snapshot_id = optional(string)
throughput = optional(number)
volume_size = number
volume_type = optional(string, "gp3")
}))
|
[
{
"volume_size": 30
}
]
| no | | [cloudwatch\_config](#input\_cloudwatch\_config) | (optional) Replaces the module default cloudwatch log config. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html for details. | `string` | `null` | no | | [create\_service\_linked\_role\_spot](#input\_create\_service\_linked\_role\_spot) | (optional) create the service linked role for spot instances that is required by the scale-up lambda. | `bool` | `false` | no | -| [disable\_runner\_autoupdate](#input\_disable\_runner\_autoupdate) | Disable the auto update of the github runner agent. Be-aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/) | `bool` | `false` | no | +| [credit\_specification](#input\_credit\_specification) | The credit option for CPU usage of a T instance. Can be unset, "standard" or "unlimited". | `string` | `null` | no | +| [disable\_runner\_autoupdate](#input\_disable\_runner\_autoupdate) | Disable the auto update of the github runner agent. Be aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/) | `bool` | `false` | no | +| [ebs\_optimized](#input\_ebs\_optimized) | The EC2 EBS optimized configuration. | `bool` | `false` | no | | [egress\_rules](#input\_egress\_rules) | List of egress rules for the GitHub runner instances. |
list(object({
cidr_blocks = list(string)
ipv6_cidr_blocks = list(string)
prefix_list_ids = list(string)
from_port = number
protocol = string
security_groups = list(string)
self = bool
to_port = number
description = string
}))
|
[
{
"cidr_blocks": [
"0.0.0.0/0"
],
"description": null,
"from_port": 0,
"ipv6_cidr_blocks": [
"::/0"
],
"prefix_list_ids": null,
"protocol": "-1",
"security_groups": null,
"self": null,
"to_port": 0
}
]
| no | | [enable\_cloudwatch\_agent](#input\_enable\_cloudwatch\_agent) | Enabling the cloudwatch agent on the ec2 runner instances, the runner contains default config. Configuration can be overridden via `cloudwatch_config`. | `bool` | `true` | no | | [enable\_ephemeral\_runners](#input\_enable\_ephemeral\_runners) | Enable ephemeral runners, runners will only be used once. | `bool` | `false` | no | +| [enable\_jit\_config](#input\_enable\_jit\_config) | Overwrite the default behavior for JIT configuration. By default JIT configuration is enabled for ephemeral runners and disabled for non-ephemeral runners. In case of GHES check first if the JIT config API is avaialbe. In case you upgradeing from 3.x to 4.x you can set `enable_jit_config` to `false` to avoid a breaking change when having your own AMI. | `bool` | `null` | no | | [enable\_job\_queued\_check](#input\_enable\_job\_queued\_check) | Only scale if the job event received by the scale up lambda is is in the state queued. By default enabled for non ephemeral runners and disabled for ephemeral. Set this variable to overwrite the default behavior. | `bool` | `null` | no | | [enable\_managed\_runner\_security\_group](#input\_enable\_managed\_runner\_security\_group) | Enabling the default managed security group creation. Unmanaged security groups can be specified via `runner_additional_security_group_ids`. | `bool` | `true` | no | -| [enable\_organization\_runners](#input\_enable\_organization\_runners) | n/a | `bool` | n/a | yes | +| [enable\_on\_demand\_failover\_for\_errors](#input\_enable\_on\_demand\_failover\_for\_errors) | Enable on-demand failover. For example to fall back to on demand when no spot capacity is available the variable can be set to `InsufficientInstanceCapacity`. When not defined the default behavior is to retry later. | `list(string)` | `[]` | no | +| [enable\_organization\_runners](#input\_enable\_organization\_runners) | Register runners to organization, instead of repo level | `bool` | n/a | yes | | [enable\_runner\_binaries\_syncer](#input\_enable\_runner\_binaries\_syncer) | Option to disable the lambda to sync GitHub runner distribution, useful when using a pre-build AMI. | `bool` | `true` | no | | [enable\_runner\_detailed\_monitoring](#input\_enable\_runner\_detailed\_monitoring) | Enable detailed monitoring for runners | `bool` | `false` | no | | [enable\_ssm\_on\_runners](#input\_enable\_ssm\_on\_runners) | Enable to allow access to the runner instances for debugging purposes via SSM. Note that this adds additional permissions to the runner instances. | `bool` | n/a | yes | | [enable\_user\_data\_debug\_logging](#input\_enable\_user\_data\_debug\_logging) | Option to enable debug logging for user-data, this logs all secrets as well. | `bool` | `false` | no | -| [enabled\_userdata](#input\_enabled\_userdata) | Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI | `bool` | `true` | no | -| [environment](#input\_environment) | A name that identifies the environment, used as prefix and for tagging. | `string` | `null` | no | +| [enable\_userdata](#input\_enable\_userdata) | Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI | `bool` | `true` | no | | [ghes\_ssl\_verify](#input\_ghes\_ssl\_verify) | GitHub Enterprise SSL verification. Set to 'false' when custom certificate (chains) is used for GitHub Enterprise Server (insecure). | `bool` | `true` | no | | [ghes\_url](#input\_ghes\_url) | GitHub Enterprise Server URL. DO NOT SET IF USING PUBLIC GITHUB | `string` | `null` | no | | [github\_app\_parameters](#input\_github\_app\_parameters) | Parameter Store for GitHub App Parameters. |
object({
key_base64 = map(string)
id = map(string)
})
| n/a | yes | -| [idle\_config](#input\_idle\_config) | List of time period that can be defined as cron expression to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle. |
list(object({
cron = string
timeZone = string
idleCount = number
}))
| `[]` | no | +| [idle\_config](#input\_idle\_config) | List of time period that can be defined as cron expression to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle. |
list(object({
cron = string
timeZone = string
idleCount = number
evictionStrategy = optional(string, "oldest_first")
}))
| `[]` | no | | [instance\_allocation\_strategy](#input\_instance\_allocation\_strategy) | The allocation strategy for spot instances. AWS recommends to use `capacity-optimized` however the AWS default is `lowest-price`. | `string` | `"lowest-price"` | no | | [instance\_max\_spot\_price](#input\_instance\_max\_spot\_price) | Max price price for spot intances per hour. This variable will be passed to the create fleet as max spot price for the fleet. | `string` | `null` | no | | [instance\_profile\_path](#input\_instance\_profile\_path) | The path that will be added to the instance\_profile, if not set the prefix will be used. | `string` | `null` | no | | [instance\_target\_capacity\_type](#input\_instance\_target\_capacity\_type) | Default lifecyle used runner instances, can be either `spot` or `on-demand`. | `string` | `"spot"` | no | -| [instance\_type](#input\_instance\_type) | [DEPRECATED] See instance\_types. | `string` | `"m5.large"` | no | -| [instance\_types](#input\_instance\_types) | List of instance types for the action runner. Defaults are based on runner\_os (amzn2 for linux and Windows Server Core for win). | `list(string)` | `null` | no | +| [instance\_types](#input\_instance\_types) | List of instance types for the action runner. Defaults are based on runner\_os (al2023 for linux and Windows Server Core for win). | `list(string)` | `null` | no | | [key\_name](#input\_key\_name) | Key pair name | `string` | `null` | no | | [kms\_key\_arn](#input\_kms\_key\_arn) | Optional CMK Key ARN to be used for Parameter Store. | `string` | `null` | no | -| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"x86_64"` | no | -| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs16.x"` | no | -| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | +| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"arm64"` | no | +| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs20.x"` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `string` | `null` | no | +| [lambda\_scale\_down\_memory\_size](#input\_lambda\_scale\_down\_memory\_size) | Memory size limit in MB for scale down lambda. | `number` | `512` | no | +| [lambda\_scale\_up\_memory\_size](#input\_lambda\_scale\_up\_memory\_size) | Memory size limit in MB for scale-up lambda. | `number` | `512` | no | | [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | | [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the lambda will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_tags](#input\_lambda\_tags) | Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags. | `map(string)` | `{}` | no | | [lambda\_timeout\_scale\_down](#input\_lambda\_timeout\_scale\_down) | Time out for the scale down lambda in seconds. | `number` | `60` | no | | [lambda\_timeout\_scale\_up](#input\_lambda\_timeout\_scale\_up) | Time out for the scale up lambda in seconds. | `number` | `60` | no | | [lambda\_zip](#input\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | | [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | -| [log\_type](#input\_log\_type) | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with | `string` | `null` | no | | [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | -| [market\_options](#input\_market\_options) | DEPCRECATED: Replaced by `instance_target_capacity_type`. | `string` | `null` | no | -| [metadata\_options](#input\_metadata\_options) | Metadata options for the ec2 runner instances. | `map(any)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "optional",
"instance_metadata_tags": "enabled"
}
| no | +| [metadata\_options](#input\_metadata\_options) | Metadata options for the ec2 runner instances. By default, the module uses metadata tags for bootstrapping the runner, only disable `instance_metadata_tags` when using custom scripts for starting the runner. | `map(any)` |
{
"http_endpoint": "enabled",
"http_put_response_hop_limit": 1,
"http_tokens": "required",
"instance_metadata_tags": "enabled"
}
| no | | [minimum\_running\_time\_in\_minutes](#input\_minimum\_running\_time\_in\_minutes) | The time an ec2 action runner should be running at minimum before terminated if non busy. If not set the default is calculated based on the OS. | `number` | `null` | no | | [overrides](#input\_overrides) | This map provides the possibility to override some defaults. The following attributes are supported: `name_sg` overrides the `Name` tag for all security groups created by this module. `name_runner_agent_instance` overrides the `Name` tag for the ec2 instance defined in the auto launch configuration. `name_docker_machine_runners` overrides the `Name` tag spot instances created by the runner agent. | `map(string)` |
{
"name_runner": "",
"name_sg": ""
}
| no | | [pool\_config](#input\_pool\_config) | The configuration for updating the pool. The `pool_size` to adjust to by the events triggered by the `schedule_expression`. For example you can configure a cron expression for week days to adjust the pool to 10 and another expression for the weekend to adjust the pool to 1. |
list(object({
schedule_expression = string
size = number
}))
| `[]` | no | +| [pool\_lambda\_memory\_size](#input\_pool\_lambda\_memory\_size) | Lambda Memory size limit in MB for pool lambda | `number` | `512` | no | | [pool\_lambda\_reserved\_concurrent\_executions](#input\_pool\_lambda\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no | | [pool\_lambda\_timeout](#input\_pool\_lambda\_timeout) | Time out for the pool lambda in seconds. | `number` | `60` | no | | [pool\_runner\_owner](#input\_pool\_runner\_owner) | The pool will deploy runners to the GitHub org ID, set this value to the org to which you want the runners deployed. Repo level is not supported. | `string` | `null` | no | @@ -173,53 +196,46 @@ yarn run dist | [runner\_as\_root](#input\_runner\_as\_root) | Run the action runner under the root user. Variable `runner_run_as` will be ignored. | `bool` | `false` | no | | [runner\_boot\_time\_in\_minutes](#input\_runner\_boot\_time\_in\_minutes) | The minimum time for an EC2 runner to boot and register as a runner. | `number` | `5` | no | | [runner\_ec2\_tags](#input\_runner\_ec2\_tags) | Map of tags that will be added to the launch template instance tag specifications. | `map(string)` | `{}` | no | -| [runner\_extra\_labels](#input\_runner\_extra\_labels) | Extra labels for the runners (GitHub). Separate each label by a comma | `string` | `""` | no | | [runner\_group\_name](#input\_runner\_group\_name) | Name of the runner group. | `string` | `"Default"` | no | | [runner\_iam\_role\_managed\_policy\_arns](#input\_runner\_iam\_role\_managed\_policy\_arns) | Attach AWS or customer-managed IAM policies (by ARN) to the runner IAM role | `list(string)` | `[]` | no | +| [runner\_labels](#input\_runner\_labels) | All the labels for the runners (GitHub) including the default one's(e.g: self-hosted, linux, x64, label1, label2). Separate each label by a comma | `list(string)` | n/a | yes | | [runner\_log\_files](#input\_runner\_log\_files) | (optional) List of logfiles to send to CloudWatch, will only be used if `enable_cloudwatch_agent` is set to true. Object description: `log_group_name`: Name of the log group, `prefix_log_group`: If true, the log group name will be prefixed with `/github-self-hosted-runners/`, `file_path`: path to the log file, `log_stream_name`: name of the log stream. |
list(object({
log_group_name = string
prefix_log_group = bool
file_path = string
log_stream_name = string
}))
| `null` | no | +| [runner\_name\_prefix](#input\_runner\_name\_prefix) | The prefix used for the GitHub runner name. The prefix will be used in the default start script to prefix the instance name when register the runner in GitHub. The value is availabe via an EC2 tag 'ghr:runner\_name\_prefix'. | `string` | `""` | no | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux,windows). | `string` | `"linux"` | no | | [runner\_run\_as](#input\_runner\_run\_as) | Run the GitHub actions agent as user. | `string` | `"ec2-user"` | no | -| [runners\_lambda\_s3\_key](#input\_runners\_lambda\_s3\_key) | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| [runners\_lambda\_s3\_object\_version](#input\_runners\_lambda\_s3\_object\_version) | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | -| [runners\_maximum\_count](#input\_runners\_maximum\_count) | The maximum number of runners that will be created. | `number` | `3` | no | +| [runners\_lambda\_s3\_key](#input\_runners\_lambda\_s3\_key) | S3 key for runners lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [runners\_lambda\_s3\_object\_version](#input\_runners\_lambda\_s3\_object\_version) | S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | +| [runners\_maximum\_count](#input\_runners\_maximum\_count) | The maximum number of runners that will be created. Setting the variable to `-1` desiables the maximum check. | `number` | `3` | no | | [s3\_runner\_binaries](#input\_s3\_runner\_binaries) | Bucket details for cached GitHub binary. |
object({
arn = string
id = string
key = string
})
| n/a | yes | | [scale\_down\_schedule\_expression](#input\_scale\_down\_schedule\_expression) | Scheduler expression to check every x for scale down. | `string` | `"cron(*/5 * * * ? *)"` | no | | [scale\_up\_reserved\_concurrent\_executions](#input\_scale\_up\_reserved\_concurrent\_executions) | Amount of reserved concurrent executions for the scale-up lambda function. A value of 0 disables lambda from being triggered and -1 removes any concurrency limitations. | `number` | `1` | no | | [sqs\_build\_queue](#input\_sqs\_build\_queue) | SQS queue to consume accepted build events. |
object({
arn = string
})
| n/a | yes | +| [ssm\_housekeeper](#input\_ssm\_housekeeper) | Configuration for the SSM housekeeper lambda. This lambda deletes token / JIT config from SSM.

`schedule_expression`: is used to configure the schedule for the lambda.
`state`: state of the cloudwatch event rule. Valid values are `DISABLED`, `ENABLED`, and `ENABLED_WITH_ALL_CLOUDTRAIL_MANAGEMENT_EVENTS`.
`lambda_memory_size`: lambda memery size limit.
`lambda_timeout`: timeout for the lambda in seconds.
`config`: configuration for the lambda function. Token path will be read by default from the module. |
object({
schedule_expression = optional(string, "rate(1 day)")
state = optional(string, "ENABLED")
lambda_memory_size = optional(number, 512)
lambda_timeout = optional(number, 60)
config = object({
tokenPath = optional(string)
minimumDaysOld = optional(number, 1)
dryRun = optional(bool, false)
})
})
|
{
"config": {}
}
| no | +| [ssm\_paths](#input\_ssm\_paths) | The root path used in SSM to store configuration and secrets. |
object({
root = string
tokens = string
config = string
})
| n/a | yes | | [subnet\_ids](#input\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | n/a | yes | | [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name. | `map(string)` | `{}` | no | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | +| [userdata\_content](#input\_userdata\_content) | Alternative user-data content, replacing the templated one. By providing your own user\_data you have to take care of installing all required software, including the action runner and registering the runner. Be-aware configuration paramaters in SSM as well as tags are treated as internals. Changes will not trigger a breaking release. | `string` | `null` | no | | [userdata\_post\_install](#input\_userdata\_post\_install) | User-data script snippet to insert after GitHub action runner install | `string` | `""` | no | | [userdata\_pre\_install](#input\_userdata\_pre\_install) | User-data script snippet to insert before GitHub action runner install | `string` | `""` | no | -| [userdata\_template](#input\_userdata\_template) | Alternative user-data template, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no | +| [userdata\_template](#input\_userdata\_template) | Alternative user-data template file path, replacing the default template. By providing your own user\_data you have to take care of installing all required software, including the action runner. Variables userdata\_pre/post\_install are ignored. | `string` | `null` | no | | [vpc\_id](#input\_vpc\_id) | The VPC for the security groups. | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| +| [lambda\_pool](#output\_lambda\_pool) | n/a | +| [lambda\_pool\_log\_group](#output\_lambda\_pool\_log\_group) | n/a | | [lambda\_scale\_down](#output\_lambda\_scale\_down) | n/a | +| [lambda\_scale\_down\_log\_group](#output\_lambda\_scale\_down\_log\_group) | n/a | | [lambda\_scale\_up](#output\_lambda\_scale\_up) | n/a | +| [lambda\_scale\_up\_log\_group](#output\_lambda\_scale\_up\_log\_group) | n/a | | [launch\_template](#output\_launch\_template) | n/a | +| [logfiles](#output\_logfiles) | List of logfiles to send to CloudWatch. Object description: `log_group_name`: Name of the log group, `file_path`: path to the log file, `log_stream_name`: name of the log stream. | | [role\_pool](#output\_role\_pool) | n/a | | [role\_runner](#output\_role\_runner) | n/a | | [role\_scale\_down](#output\_role\_scale\_down) | n/a | | [role\_scale\_up](#output\_role\_scale\_up) | n/a | - - -## Philips Forest - -This module is part of the Philips Forest. - -```plain - ___ _ - / __\__ _ __ ___ ___| |_ - / _\/ _ \| '__/ _ \/ __| __| - / / | (_) | | | __/\__ \ |_ - \/ \___/|_| \___||___/\__| - - Infrastructure -``` - -Talk to the forestkeepers in the `forest`-channel on Slack. - -[![Slack](https://philips-software-slackin.now.sh/badge.svg)](https://philips-software-slackin.now.sh) +| [runners\_log\_groups](#output\_runners\_log\_groups) | List of log groups from different log files of runner machine. | + diff --git a/modules/runners/lambdas/.gitignore b/modules/runners/lambdas/.gitignore deleted file mode 100644 index 981918a850..0000000000 --- a/modules/runners/lambdas/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# dependencies -node_modules/ - -# production -dist/ -build/ - -# misc -.DS_Store -.env* -*.zip - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/modules/runners/lambdas/runners/.eslintrc.yaml b/modules/runners/lambdas/runners/.eslintrc.yaml deleted file mode 100644 index 682ae5cefa..0000000000 --- a/modules/runners/lambdas/runners/.eslintrc.yaml +++ /dev/null @@ -1,23 +0,0 @@ -env: - browser: true - es2021: true -extends: - #- google - - eslint:recommended - - plugin:@typescript-eslint/recommended -parser: "@typescript-eslint/parser" -parserOptions: - ecmaVersion: 12 - sourceType: module -plugins: - - "@typescript-eslint" -rules: - semi: error - max-len: - - error - - 120 - -overrides: - - files: - - "*.ts" - - "*.tsx" diff --git a/modules/runners/lambdas/runners/.nvmrc b/modules/runners/lambdas/runners/.nvmrc deleted file mode 100644 index 6f7f377bf5..0000000000 --- a/modules/runners/lambdas/runners/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v16 diff --git a/modules/runners/lambdas/runners/.prettierrc b/modules/runners/lambdas/runners/.prettierrc deleted file mode 100644 index 3eb40208ef..0000000000 --- a/modules/runners/lambdas/runners/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "printWidth": 120, - "singleQuote": true, - "trailingComma": "all", - "semi": true, - "importOrderSeparation": true, - "importOrderSortSpecifiers": true, - "importOrder": [ - "", - "^[./]" - ] -} \ No newline at end of file diff --git a/modules/runners/lambdas/runners/jest.config.js b/modules/runners/lambdas/runners/jest.config.js deleted file mode 100644 index 165378f519..0000000000 --- a/modules/runners/lambdas/runners/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - collectCoverage: true, - collectCoverageFrom: ['src/**/*.{ts,js,jsx}', '!src/**/*local*.ts', 'src/**/*.d.ts'], - coverageThreshold: { - global: { - branches: 92, - functions: 92, - lines: 92, - statements: 92, - }, - }, -}; diff --git a/modules/runners/lambdas/runners/package.json b/modules/runners/lambdas/runners/package.json deleted file mode 100644 index 5a547de4cc..0000000000 --- a/modules/runners/lambdas/runners/package.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "name": "github-runner-lambda-scale-runners", - "version": "1.0.0", - "main": "lambda.ts", - "license": "MIT", - "scripts": { - "start": "ts-node-dev src/local.ts", - "test": "NODE_ENV=test jest", - "test:watch": "NODE_ENV=test jest --watch", - "lint": "yarn eslint src", - "watch": "ts-node-dev --respawn --exit-child src/local.ts", - "build": "ncc build src/lambda.ts -o dist", - "dist": "yarn build && cd dist && zip ../runners.zip index.js", - "format": "prettier --write \"**/*.ts\"", - "format-check": "prettier --check \"**/*.ts\"", - "all": "yarn build && yarn format && yarn lint && yarn test" - }, - "devDependencies": { - "@trivago/prettier-plugin-sort-imports": "^4.0.0", - "@types/aws-lambda": "^8.10.109", - "@types/express": "^4.17.15", - "@types/jest": "^29.2.4", - "@types/node": "^18.11.18", - "@typescript-eslint/eslint-plugin": "^5.47.1", - "@typescript-eslint/parser": "^5.47.1", - "@vercel/ncc": "^0.36.0", - "eslint": "^8.30.0", - "eslint-plugin-prettier": "4.2.1", - "jest": "^29.3", - "jest-mock": "^29.3.1", - "jest-mock-extended": "^3.0.1", - "moment-timezone": "^0.5.40", - "nock": "^13.2.9", - "prettier": "2.8.1", - "ts-jest": "^29.0.3", - "ts-node": "^10.9.1", - "ts-node-dev": "^2.0.0" - }, - "dependencies": { - "@aws-sdk/client-ssm": "^3.238.0", - "@octokit/auth-app": "4.0.7", - "@octokit/rest": "^19.0.5", - "@octokit/types": "^8.0.0", - "aws-sdk": "^2.1283.0", - "cron-parser": "^4.7.0", - "tslog": "^3.3.4", - "typescript": "^4.9.4" - } -} diff --git a/modules/runners/lambdas/runners/src/aws/runners.test.ts b/modules/runners/lambdas/runners/src/aws/runners.test.ts deleted file mode 100644 index 15a1772ab4..0000000000 --- a/modules/runners/lambdas/runners/src/aws/runners.test.ts +++ /dev/null @@ -1,518 +0,0 @@ -import { EC2 } from 'aws-sdk'; - -import ScaleError from './../scale-runners/ScaleError'; -import { RunnerInfo, RunnerInputParameters, createRunner, listEC2Runners, terminateRunner } from './runners'; - -const mockEC2 = { describeInstances: jest.fn(), createFleet: jest.fn(), terminateInstances: jest.fn() }; -const mockSSM = { putParameter: jest.fn(), getParameter: jest.fn() }; -jest.mock('aws-sdk', () => ({ - EC2: jest.fn().mockImplementation(() => mockEC2), - SSM: jest.fn().mockImplementation(() => mockSSM), -})); - -const LAUNCH_TEMPLATE = 'lt-1'; -const ORG_NAME = 'SomeAwesomeCoder'; -const REPO_NAME = `${ORG_NAME}/some-amazing-library`; -const ENVIRONMENT = 'unit-test-environment'; - -const mockDescribeInstances = { promise: jest.fn() }; -mockEC2.describeInstances.mockImplementation(() => mockDescribeInstances); -const mockRunningInstances: AWS.EC2.DescribeInstancesResult = { - Reservations: [ - { - Instances: [ - { - LaunchTime: new Date('2020-10-10T14:48:00.000+09:00'), - InstanceId: 'i-1234', - Tags: [ - { Key: 'ghr:Application', Value: 'github-action-runner' }, - { Key: 'Type', Value: 'Org' }, - { Key: 'Owner', Value: 'CoderToCat' }, - ], - }, - ], - }, - ], -}; -const mockRunningInstancesLegacy: AWS.EC2.DescribeInstancesResult = { - Reservations: [ - { - Instances: [ - { - LaunchTime: new Date('2020-10-11T14:48:00.000+09:00'), - InstanceId: 'i-5678', - Tags: [ - { Key: 'Owner', Value: REPO_NAME }, - { Key: 'Type', Value: 'Repo' }, - { Key: 'Application', Value: 'github-action-runner' }, - ], - }, - ], - }, - ], -}; - -describe('list instances', () => { - beforeEach(() => { - jest.resetModules(); - jest.clearAllMocks(); - }); - - it('returns a list of instances', async () => { - mockDescribeInstances.promise - .mockReturnValueOnce(mockRunningInstances) - .mockReturnValueOnce(mockRunningInstancesLegacy); - const resp = await listEC2Runners(); - expect(resp.length).toBe(2); - expect(resp).toContainEqual({ - instanceId: 'i-1234', - launchTime: new Date('2020-10-10T14:48:00.000+09:00'), - type: 'Org', - owner: 'CoderToCat', - }); - expect(resp).toContainEqual({ - instanceId: 'i-5678', - launchTime: new Date('2020-10-11T14:48:00.000+09:00'), - type: 'Repo', - owner: REPO_NAME, - }); - }); - - it('calls EC2 describe instances', async () => { - mockDescribeInstances.promise - .mockReturnValueOnce(mockRunningInstances) - .mockReturnValueOnce(mockRunningInstancesLegacy); - await listEC2Runners(); - expect(mockEC2.describeInstances).toBeCalled(); - }); - - it('filters instances on repo name', async () => { - mockDescribeInstances.promise - .mockReturnValueOnce(mockRunningInstances) - .mockReturnValueOnce(mockRunningInstancesLegacy); - await listEC2Runners({ runnerType: 'Repo', runnerOwner: REPO_NAME, environment: undefined }); - expect(mockEC2.describeInstances).toBeCalledWith({ - Filters: [ - { Name: 'instance-state-name', Values: ['running', 'pending'] }, - { Name: 'tag:Type', Values: ['Repo'] }, - { Name: 'tag:Owner', Values: [REPO_NAME] }, - { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, - ], - }); - expect(mockEC2.describeInstances).toBeCalledWith({ - Filters: [ - { Name: 'instance-state-name', Values: ['running', 'pending'] }, - { Name: 'tag:Type', Values: ['Repo'] }, - { Name: 'tag:Owner', Values: [REPO_NAME] }, - { Name: 'tag:Application', Values: ['github-action-runner'] }, - ], - }); - }); - - it('filters instances on org name', async () => { - mockDescribeInstances.promise - .mockReturnValueOnce(mockRunningInstances) - .mockReturnValueOnce(mockRunningInstancesLegacy); - await listEC2Runners({ runnerType: 'Org', runnerOwner: ORG_NAME, environment: undefined }); - expect(mockEC2.describeInstances).toBeCalledWith({ - Filters: [ - { Name: 'instance-state-name', Values: ['running', 'pending'] }, - { Name: 'tag:Type', Values: ['Org'] }, - { Name: 'tag:Owner', Values: [ORG_NAME] }, - { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, - ], - }); - }); - - it('filters instances on environment', async () => { - mockDescribeInstances.promise - .mockReturnValueOnce(mockRunningInstances) - .mockReturnValueOnce(mockRunningInstancesLegacy); - await listEC2Runners({ environment: ENVIRONMENT }); - expect(mockEC2.describeInstances).toBeCalledWith({ - Filters: [ - { Name: 'instance-state-name', Values: ['running', 'pending'] }, - { Name: 'tag:ghr:environment', Values: [ENVIRONMENT] }, - { Name: 'tag:ghr:Application', Values: ['github-action-runner'] }, - ], - }); - }); - - it('No instances, undefined reservations list.', async () => { - const noInstances: AWS.EC2.DescribeInstancesResult = { - Reservations: undefined, - }; - mockDescribeInstances.promise.mockReturnValue(noInstances); - const resp = await listEC2Runners(); - expect(resp.length).toBe(0); - }); - - it('No instances, undefined instance list.', async () => { - const noInstances: AWS.EC2.DescribeInstancesResult = { - Reservations: [ - { - Instances: undefined, - }, - ], - }; - mockDescribeInstances.promise.mockReturnValueOnce(noInstances).mockReturnValueOnce(noInstances); - const resp = await listEC2Runners(); - expect(resp.length).toBe(0); - }); - - it('Instances with no tags.', async () => { - const noInstances: AWS.EC2.DescribeInstancesResult = { - Reservations: [ - { - Instances: [ - { - LaunchTime: new Date('2020-10-11T14:48:00.000+09:00'), - InstanceId: 'i-5678', - Tags: undefined, - }, - ], - }, - ], - }; - mockDescribeInstances.promise.mockReturnValueOnce(noInstances).mockReturnValue({}); - const resp = await listEC2Runners(); - expect(resp.length).toBe(1); - }); -}); - -describe('terminate runner', () => { - const mockTerminateInstances = { promise: jest.fn() }; - beforeEach(() => { - jest.clearAllMocks(); - mockEC2.terminateInstances.mockImplementation(() => mockTerminateInstances); - mockTerminateInstances.promise.mockReturnThis(); - }); - it('calls terminate instances with the right instance ids', async () => { - const runner: RunnerInfo = { - instanceId: 'instance-2', - owner: 'owner-2', - type: 'Repo', - }; - await terminateRunner(runner.instanceId); - - expect(mockEC2.terminateInstances).toBeCalledWith({ InstanceIds: [runner.instanceId] }); - }); -}); - -describe('create runner', () => { - const mockCreateFleet = { promise: jest.fn() }; - const mockPutParameter = { promise: jest.fn() }; - const mockGetParameter = { promise: jest.fn() }; - - const defaultRunnerConfig: RunnerConfig = { - allocationStrategy: 'capacity-optimized', - capacityType: 'spot', - type: 'Org', - }; - const defaultExpectedFleetRequestValues: ExpectedFleetRequestValues = { - type: 'Org', - capacityType: 'spot', - allocationStrategy: 'capacity-optimized', - totalTargetCapacity: 1, - }; - - beforeEach(() => { - jest.clearAllMocks(); - - mockEC2.createFleet.mockImplementation(() => mockCreateFleet); - - mockCreateFleet.promise.mockReturnValue({ - Instances: [{ InstanceIds: ['i-1234'] }], - }); - mockSSM.putParameter.mockImplementation(() => mockPutParameter); - - mockSSM.getParameter.mockImplementation(() => mockGetParameter); - }); - - it('calls create fleet of 1 instance with the correct config for repo', async () => { - await createRunner(createRunnerConfig({ ...defaultRunnerConfig, type: 'Repo' })); - expect(mockEC2.createFleet).toBeCalledWith( - expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, type: 'Repo' }), - ); - expect(mockSSM.putParameter).toBeCalledTimes(1); - }); - - it('calls create fleet of 2 instances with the correct config for org ', async () => { - const instances = [{ InstanceIds: ['i-1234', 'i-5678'] }]; - mockCreateFleet.promise.mockReturnValue({ - Instances: instances, - }); - - await createRunner({ ...createRunnerConfig(defaultRunnerConfig), numberOfRunners: 2 }); - - expect(mockEC2.createFleet).toBeCalledWith( - expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, totalTargetCapacity: 2 }), - ); - expect(mockSSM.putParameter).toBeCalledTimes(2); - for (const instance of instances[0].InstanceIds) { - expect(mockSSM.putParameter).toBeCalledWith({ - Name: `unit-test-environment-${instance}`, - Type: 'SecureString', - Value: '--token foo --url http://github.com', - }); - } - }); - - it('calls create fleet of 1 instance with the correct config for org', async () => { - await createRunner(createRunnerConfig(defaultRunnerConfig)); - expect(mockEC2.createFleet).toBeCalledWith(expectedCreateFleetRequest(defaultExpectedFleetRequestValues)); - expect(mockSSM.putParameter).toBeCalledTimes(1); - }); - - it('calls create fleet of 1 instance with the on-demand capacity', async () => { - await createRunner(createRunnerConfig({ ...defaultRunnerConfig, capacityType: 'on-demand' })); - expect(mockEC2.createFleet).toBeCalledWith( - expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, capacityType: 'on-demand' }), - ); - expect(mockSSM.putParameter).toBeCalledTimes(1); - }); - - it('calls run instances with the on-demand capacity', async () => { - await createRunner(createRunnerConfig({ ...defaultRunnerConfig, maxSpotPrice: '0.1' })); - expect(mockEC2.createFleet).toBeCalledWith( - expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, maxSpotPrice: '0.1' }), - ); - }); - - it('creates ssm parameters for each created instance', async () => { - await createRunner(createRunnerConfig(defaultRunnerConfig)); - expect(mockSSM.putParameter).toBeCalledWith({ - Name: `${ENVIRONMENT}-i-1234`, - Value: '--token foo --url http://github.com', - Type: 'SecureString', - }); - }); - - it('does not create ssm parameters when no instance is created', async () => { - mockCreateFleet.promise.mockReturnValue({ - Instances: [], - }); - await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toThrowError(Error); - expect(mockSSM.putParameter).not.toBeCalled(); - }); - - it('uses ami id from ssm parameter when ami id ssm param is specified', async () => { - const paramValue: AWS.SSM.GetParameterResult = { - Parameter: { - Value: 'ami-123', - }, - }; - mockGetParameter.promise.mockReturnValue(paramValue); - await createRunner(createRunnerConfig({ ...defaultRunnerConfig, amiIdSsmParameterName: 'my-ami-id-param' })); - const expectedRequest = expectedCreateFleetRequest({ ...defaultExpectedFleetRequestValues, imageId: 'ami-123' }); - expect(mockEC2.createFleet).toBeCalledWith(expectedRequest); - expect(mockSSM.getParameter).toBeCalledWith({ - Name: 'my-ami-id-param', - }); - }); -}); - -describe('create runner with errors', () => { - const defaultRunnerConfig: RunnerConfig = { - allocationStrategy: 'capacity-optimized', - capacityType: 'spot', - type: 'Repo', - }; - const defaultExpectedFleetRequestValues: ExpectedFleetRequestValues = { - type: 'Repo', - capacityType: 'spot', - allocationStrategy: 'capacity-optimized', - totalTargetCapacity: 1, - }; - beforeEach(() => { - jest.clearAllMocks(); - - const mockPutParameter = { promise: jest.fn() }; - - mockSSM.putParameter.mockImplementation(() => mockPutParameter); - - const mockGetParameter = { promise: jest.fn() }; - - mockSSM.getParameter.mockImplementation(() => mockGetParameter); - }); - - it('test ScaleError with one error.', async () => { - createFleetMockWithErrors(['UnfulfillableCapacity']); - - await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(ScaleError); - expect(mockEC2.createFleet).toBeCalledWith(expectedCreateFleetRequest(defaultExpectedFleetRequestValues)); - expect(mockSSM.putParameter).not.toBeCalled(); - }); - - it('test ScaleError with multiple error.', async () => { - createFleetMockWithErrors(['UnfulfillableCapacity', 'SomeError']); - - await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(ScaleError); - expect(mockEC2.createFleet).toBeCalledWith(expectedCreateFleetRequest(defaultExpectedFleetRequestValues)); - expect(mockSSM.putParameter).not.toBeCalled(); - }); - - it('test default Error', async () => { - createFleetMockWithErrors(['NonMappedError']); - - await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(Error); - expect(mockEC2.createFleet).toBeCalledWith(expectedCreateFleetRequest(defaultExpectedFleetRequestValues)); - expect(mockSSM.putParameter).not.toBeCalled(); - }); - - it('test now error is thrown if an instance is created', async () => { - createFleetMockWithErrors(['NonMappedError'], ['i-123']); - - expect(await createRunner(createRunnerConfig(defaultRunnerConfig))).resolves; - expect(mockEC2.createFleet).toBeCalledWith(expectedCreateFleetRequest(defaultExpectedFleetRequestValues)); - expect(mockSSM.putParameter).toBeCalled(); - }); - - it('test error by create fleet call is thrown.', async () => { - mockEC2.createFleet.mockImplementation(() => { - return { - promise: jest.fn().mockImplementation(() => { - throw Error(''); - }), - }; - }); - - await expect(createRunner(createRunnerConfig(defaultRunnerConfig))).rejects.toBeInstanceOf(Error); - expect(mockEC2.createFleet).toBeCalledWith(expectedCreateFleetRequest(defaultExpectedFleetRequestValues)); - expect(mockSSM.putParameter).not.toBeCalled(); - }); - - it('test error in ami id lookup from ssm parameter', async () => { - mockSSM.getParameter.mockImplementation(() => { - return { - promise: jest.fn().mockImplementation(() => { - throw Error('Wow, such transient'); - }), - }; - }); - - await expect( - createRunner(createRunnerConfig({ ...defaultRunnerConfig, amiIdSsmParameterName: 'my-ami-id-param' })), - ).rejects.toBeInstanceOf(Error); - expect(mockEC2.createFleet).not.toBeCalled(); - expect(mockSSM.putParameter).not.toBeCalled(); - }); -}); - -function createFleetMockWithErrors(errors: string[], instances?: string[]) { - let result: AWS.EC2.CreateFleetResult = { - Errors: errors.map((e) => ({ ErrorCode: e })), - }; - - if (instances) { - result = { - ...result, - Instances: [ - { - InstanceIds: instances.map((i) => i), - }, - ], - }; - } - - mockEC2.createFleet.mockImplementation(() => { - return { promise: jest.fn().mockReturnValue(result) }; - }); -} - -interface RunnerConfig { - type: 'Repo' | 'Org'; - capacityType: EC2.DefaultTargetCapacityType; - allocationStrategy: EC2.AllocationStrategy; - maxSpotPrice?: string; - amiIdSsmParameterName?: string; -} - -function createRunnerConfig(runnerConfig: RunnerConfig): RunnerInputParameters { - return { - runnerServiceConfig: ['--token foo', '--url http://github.com'], - environment: ENVIRONMENT, - runnerType: runnerConfig.type, - runnerOwner: REPO_NAME, - launchTemplateName: LAUNCH_TEMPLATE, - ec2instanceCriteria: { - instanceTypes: ['m5.large', 'c5.large'], - targetCapacityType: runnerConfig.capacityType, - maxSpotPrice: runnerConfig.maxSpotPrice, - instanceAllocationStrategy: runnerConfig.allocationStrategy, - }, - subnets: ['subnet-123', 'subnet-456'], - amiIdSsmParameterName: runnerConfig.amiIdSsmParameterName, - }; -} - -interface ExpectedFleetRequestValues { - type: 'Repo' | 'Org'; - capacityType: EC2.DefaultTargetCapacityType; - allocationStrategy: EC2.AllocationStrategy; - maxSpotPrice?: string; - totalTargetCapacity: number; - imageId?: string; -} - -function expectedCreateFleetRequest(expectedValues: ExpectedFleetRequestValues): AWS.EC2.CreateFleetRequest { - const request: AWS.EC2.CreateFleetRequest = { - LaunchTemplateConfigs: [ - { - LaunchTemplateSpecification: { - LaunchTemplateName: 'lt-1', - Version: '$Default', - }, - Overrides: [ - { - InstanceType: 'm5.large', - SubnetId: 'subnet-123', - }, - { - InstanceType: 'c5.large', - SubnetId: 'subnet-123', - }, - { - InstanceType: 'm5.large', - SubnetId: 'subnet-456', - }, - { - InstanceType: 'c5.large', - SubnetId: 'subnet-456', - }, - ], - }, - ], - SpotOptions: { - AllocationStrategy: expectedValues.allocationStrategy, - MaxTotalPrice: expectedValues.maxSpotPrice, - }, - TagSpecifications: [ - { - ResourceType: 'instance', - Tags: [ - { Key: 'ghr:Application', Value: 'github-action-runner' }, - { Key: 'Type', Value: expectedValues.type }, - { Key: 'Owner', Value: REPO_NAME }, - ], - }, - ], - TargetCapacitySpecification: { - DefaultTargetCapacityType: expectedValues.capacityType, - TotalTargetCapacity: expectedValues.totalTargetCapacity, - }, - Type: 'instant', - }; - - if (expectedValues.imageId) { - for (const config of request.LaunchTemplateConfigs) { - if (config.Overrides) { - for (const override of config.Overrides) { - override.ImageId = expectedValues.imageId; - } - } - } - } - - return request; -} diff --git a/modules/runners/lambdas/runners/src/aws/runners.ts b/modules/runners/lambdas/runners/src/aws/runners.ts deleted file mode 100644 index 6784853a01..0000000000 --- a/modules/runners/lambdas/runners/src/aws/runners.ts +++ /dev/null @@ -1,270 +0,0 @@ -import { EC2, SSM } from 'aws-sdk'; - -import { LogFields, logger as rootLogger } from '../logger'; -import ScaleError from './../scale-runners/ScaleError'; - -const logger = rootLogger.getChildLogger({ name: 'runners' }); - -export interface RunnerList { - instanceId: string; - launchTime?: Date; - owner?: string; - type?: string; - repo?: string; - org?: string; -} - -export interface RunnerInfo { - instanceId: string; - launchTime?: Date; - owner: string; - type: string; -} - -export interface ListRunnerFilters { - runnerType?: 'Org' | 'Repo'; - runnerOwner?: string; - environment?: string; - statuses?: string[]; -} - -export interface RunnerInputParameters { - runnerServiceConfig: string[]; - environment: string; - runnerType: 'Org' | 'Repo'; - runnerOwner: string; - subnets: string[]; - launchTemplateName: string; - ec2instanceCriteria: { - instanceTypes: string[]; - targetCapacityType: EC2.DefaultTargetCapacityType; - maxSpotPrice?: string; - instanceAllocationStrategy: EC2.SpotAllocationStrategy; - }; - numberOfRunners?: number; - amiIdSsmParameterName?: string; -} - -interface Ec2Filter { - Name: string; - Values: string[]; -} - -export async function listEC2Runners(filters: ListRunnerFilters | undefined = undefined): Promise { - const ec2Filters = constructFilters(filters); - const runners: RunnerList[] = []; - for (const filter of ec2Filters) { - runners.push(...(await getRunners(filter))); - } - return runners; -} - -function constructFilters(filters?: ListRunnerFilters): Ec2Filter[][] { - const ec2Statuses = filters?.statuses ? filters.statuses : ['running', 'pending']; - const ec2Filters: Ec2Filter[][] = []; - const ec2FiltersBase = [{ Name: 'instance-state-name', Values: ec2Statuses }]; - if (filters) { - if (filters.environment !== undefined) { - ec2FiltersBase.push({ Name: 'tag:ghr:environment', Values: [filters.environment] }); - } - if (filters.runnerType && filters.runnerOwner) { - ec2FiltersBase.push({ Name: `tag:Type`, Values: [filters.runnerType] }); - ec2FiltersBase.push({ Name: `tag:Owner`, Values: [filters.runnerOwner] }); - } - } - - // ***Deprecation Notice*** - // Support for legacy `Application` tag keys - // will be removed in next major release. - for (const key of ['tag:ghr:Application', 'tag:Application']) { - const filter = [...ec2FiltersBase]; - filter.push({ Name: key, Values: ['github-action-runner'] }); - ec2Filters.push(filter); - } - return ec2Filters; -} - -async function getRunners(ec2Filters: Ec2Filter[]): Promise { - const ec2 = new EC2(); - const runners: RunnerList[] = []; - let nextToken; - let hasNext = true; - while (hasNext) { - const runningInstances: EC2.DescribeInstancesResult = await ec2 - .describeInstances({ Filters: ec2Filters, NextToken: nextToken }) - .promise(); - hasNext = runningInstances.NextToken ? true : false; - nextToken = runningInstances.NextToken; - runners.push(...getRunnerInfo(runningInstances)); - } - return runners; -} - -function getRunnerInfo(runningInstances: EC2.DescribeInstancesResult) { - const runners: RunnerList[] = []; - if (runningInstances.Reservations) { - for (const r of runningInstances.Reservations) { - if (r.Instances) { - for (const i of r.Instances) { - runners.push({ - instanceId: i.InstanceId as string, - launchTime: i.LaunchTime, - owner: i.Tags?.find((e) => e.Key === 'Owner')?.Value as string, - type: i.Tags?.find((e) => e.Key === 'Type')?.Value as string, - repo: i.Tags?.find((e) => e.Key === 'Repo')?.Value as string, - org: i.Tags?.find((e) => e.Key === 'Org')?.Value as string, - }); - } - } - } - } - return runners; -} - -export async function terminateRunner(instanceId: string): Promise { - const ec2 = new EC2(); - await ec2 - .terminateInstances({ - InstanceIds: [instanceId], - }) - .promise(); - logger.info(`Runner ${instanceId} has been terminated.`, LogFields.print()); -} - -function generateFleetOverrides( - subnetIds: string[], - instancesTypes: string[], - amiId?: string, -): EC2.FleetLaunchTemplateOverridesListRequest { - type Override = { - SubnetId: string; - InstanceType: string; - ImageId?: string; - }; - const result: EC2.FleetLaunchTemplateOverridesListRequest = []; - subnetIds.forEach((s) => { - instancesTypes.forEach((i) => { - const item: Override = { - SubnetId: s, - InstanceType: i, - }; - if (amiId) { - item.ImageId = amiId; - } - result.push(item); - }); - }); - return result; -} - -export async function createRunner(runnerParameters: RunnerInputParameters): Promise { - logger.debug('Runner configuration: ' + JSON.stringify(runnerParameters), LogFields.print()); - - const ec2 = new EC2(); - const ssm = new SSM(); - - let amiIdOverride = undefined; - - if (runnerParameters.amiIdSsmParameterName) { - logger.debug(`Looking up runner AMI ID from SSM parameter: ${runnerParameters.amiIdSsmParameterName}`); - try { - const result: AWS.SSM.GetParameterResult = await ssm - .getParameter({ Name: runnerParameters.amiIdSsmParameterName }) - .promise(); - amiIdOverride = result.Parameter?.Value; - } catch (e) { - logger.error( - `Failed to lookup runner AMI ID from SSM parameter: ${runnerParameters.amiIdSsmParameterName}. ` + - 'Please ensure that the given parameter exists on this region and contains a valid runner AMI ID', - e, - ); - throw e; - } - } - - const numberOfRunners = runnerParameters.numberOfRunners ? runnerParameters.numberOfRunners : 1; - - let fleet: AWS.EC2.CreateFleetResult; - try { - // see for spec https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateFleet.html - fleet = await ec2 - .createFleet({ - LaunchTemplateConfigs: [ - { - LaunchTemplateSpecification: { - LaunchTemplateName: runnerParameters.launchTemplateName, - Version: '$Default', - }, - Overrides: generateFleetOverrides( - runnerParameters.subnets, - runnerParameters.ec2instanceCriteria.instanceTypes, - amiIdOverride, - ), - }, - ], - SpotOptions: { - MaxTotalPrice: runnerParameters.ec2instanceCriteria.maxSpotPrice, - AllocationStrategy: runnerParameters.ec2instanceCriteria.instanceAllocationStrategy, - }, - TargetCapacitySpecification: { - TotalTargetCapacity: numberOfRunners, - DefaultTargetCapacityType: runnerParameters.ec2instanceCriteria.targetCapacityType, - }, - TagSpecifications: [ - { - ResourceType: 'instance', - Tags: [ - { Key: 'ghr:Application', Value: 'github-action-runner' }, - { Key: 'Type', Value: runnerParameters.runnerType }, - { Key: 'Owner', Value: runnerParameters.runnerOwner }, - ], - }, - ], - Type: 'instant', - }) - .promise(); - } catch (e) { - logger.warn('Create fleet request failed.', e); - throw e; - } - - const instances: string[] = fleet.Instances?.flatMap((i) => i.InstanceIds?.flatMap((j) => j) || []) || []; - - if (instances.length === 0) { - logger.warn(`No instances created by fleet request. Check configuration! Response:`, fleet); - const errors = fleet.Errors?.flatMap((e) => e.ErrorCode || '') || []; - - // Educated guess of errors that would make sense to retry based on the list - // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html - const scaleErrors = [ - 'UnfulfillableCapacity', - 'MaxSpotInstanceCountExceeded', - 'TargetCapacityLimitExceededException', - 'RequestLimitExceeded', - 'ResourceLimitExceeded', - 'MaxSpotInstanceCountExceeded', - 'MaxSpotFleetRequestCountExceeded', - ]; - - if (errors.some((e) => scaleErrors.includes(e))) { - logger.warn('Create fleet failed, ScaleError will be thrown to trigger retry for ephemeral runners.'); - logger.debug('Create fleet failed.', fleet.Errors); - throw new ScaleError('Failed to create instance, create fleet failed.'); - } else { - logger.warn('Create fleet failed, error not recognized as scaling error.', fleet.Errors); - throw Error('Create fleet failed, no instance created.'); - } - } - - logger.info('Created instance(s): ', instances.join(','), LogFields.print()); - - for (const instance of instances) { - await ssm - .putParameter({ - Name: `${runnerParameters.environment}-${instance}`, - Value: runnerParameters.runnerServiceConfig.join(' '), - Type: 'SecureString', - }) - .promise(); - } -} diff --git a/modules/runners/lambdas/runners/src/aws/ssm.test.ts b/modules/runners/lambdas/runners/src/aws/ssm.test.ts deleted file mode 100644 index 8cd82b0d46..0000000000 --- a/modules/runners/lambdas/runners/src/aws/ssm.test.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { GetParameterCommandOutput, SSM } from '@aws-sdk/client-ssm'; -import nock from 'nock'; - -import { getParameterValue } from './ssm'; - -jest.mock('@aws-sdk/client-ssm'); - -const cleanEnv = process.env; - -beforeEach(() => { - jest.resetModules(); - jest.clearAllMocks(); - process.env = { ...cleanEnv }; - nock.disableNetConnect(); -}); - -describe('Test getParameterValue', () => { - test('Gets parameters and returns string', async () => { - // Arrange - const parameterValue = 'test'; - const parameterName = 'testParam'; - const output: GetParameterCommandOutput = { - Parameter: { - Name: parameterName, - Type: 'SecureString', - Value: parameterValue, - }, - $metadata: { - httpStatusCode: 200, - }, - }; - - SSM.prototype.getParameter = jest.fn().mockResolvedValue(output); - - // Act - const result = await getParameterValue(parameterName); - - // Assert - expect(result).toBe(parameterValue); - }); - - test('Gets invalid parameters and returns string', async () => { - // Arrange - const parameterName = 'invalid'; - const output: GetParameterCommandOutput = { - $metadata: { - httpStatusCode: 200, - }, - }; - - SSM.prototype.getParameter = jest.fn().mockResolvedValue(output); - - // Act - const result = await getParameterValue(parameterName); - - // Assert - expect(result).toBe(undefined); - }); -}); diff --git a/modules/runners/lambdas/runners/src/aws/ssm.ts b/modules/runners/lambdas/runners/src/aws/ssm.ts deleted file mode 100644 index 5212914321..0000000000 --- a/modules/runners/lambdas/runners/src/aws/ssm.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { SSM } from '@aws-sdk/client-ssm'; - -export async function getParameterValue(parameter_name: string): Promise { - const client = new SSM({ region: process.env.AWS_REGION }); - return (await client.getParameter({ Name: parameter_name, WithDecryption: true })).Parameter?.Value as string; -} diff --git a/modules/runners/lambdas/runners/src/lambda.ts b/modules/runners/lambdas/runners/src/lambda.ts deleted file mode 100644 index a74b540dab..0000000000 --- a/modules/runners/lambdas/runners/src/lambda.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Context, SQSEvent } from 'aws-lambda'; -import 'source-map-support/register'; - -import { LogFields, logger } from './logger'; -import { PoolEvent, adjust } from './pool/pool'; -import ScaleError from './scale-runners/ScaleError'; -import { scaleDown } from './scale-runners/scale-down'; -import { scaleUp } from './scale-runners/scale-up'; - -export async function scaleUpHandler(event: SQSEvent, context: Context): Promise { - logger.setSettings({ requestId: context.awsRequestId }); - logger.debug(JSON.stringify(event)); - - if (event.Records.length !== 1) { - logger.warn( - 'Event ignored, only one record at the time can be handled, ensure the lambda batch size is set to 1.', - LogFields.print(), - ); - return new Promise((resolve) => resolve()); - } - - try { - await scaleUp(event.Records[0].eventSource, JSON.parse(event.Records[0].body)); - } catch (e) { - if (e instanceof ScaleError) { - throw e; - } else { - logger.warn(`Ignoring error: ${(e as Error).message}`, LogFields.print()); - } - } -} - -export async function scaleDownHandler(context: Context): Promise { - logger.setSettings({ requestId: context.awsRequestId }); - - try { - await scaleDown(); - } catch (e) { - logger.error(e); - } -} - -export async function adjustPool(event: PoolEvent, context: Context): Promise { - logger.setSettings({ requestId: context.awsRequestId }); - - try { - await adjust(event); - } catch (e) { - logger.error(e); - } -} diff --git a/modules/runners/lambdas/runners/src/logger.ts b/modules/runners/lambdas/runners/src/logger.ts deleted file mode 100644 index e7f4a49e10..0000000000 --- a/modules/runners/lambdas/runners/src/logger.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Logger } from 'tslog'; - -export const logger = new Logger({ - colorizePrettyLogs: false, - displayInstanceName: false, - maskAnyRegEx: ['--token [A-Z0-9]*'], - minLevel: process.env.LOG_LEVEL || 'info', - name: 'scale-runners', - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', -}); -export class LogFields { - static fields: { [key: string]: string } = {}; - - public static print(): string { - return JSON.stringify(LogFields.fields); - } -} diff --git a/modules/runners/lambdas/runners/src/pool/pool.test.ts b/modules/runners/lambdas/runners/src/pool/pool.test.ts deleted file mode 100644 index 17973b1ee6..0000000000 --- a/modules/runners/lambdas/runners/src/pool/pool.test.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { Octokit } from '@octokit/rest'; -import { mocked } from 'jest-mock'; -import nock from 'nock'; - -import { listEC2Runners } from '../aws/runners'; -import * as ghAuth from '../gh-auth/gh-auth'; -import * as scale from '../scale-runners/scale-up'; -import { adjust } from './pool'; - -const mockOctokit = { - paginate: jest.fn(), - checks: { get: jest.fn() }, - actions: { - createRegistrationTokenForOrg: jest.fn(), - }, - apps: { - getOrgInstallation: jest.fn(), - }, -}; - -jest.mock('@octokit/rest', () => ({ - Octokit: jest.fn().mockImplementation(() => mockOctokit), -})); - -jest.mock('./../aws/runners'); -jest.mock('./../gh-auth/gh-auth'); - -const mocktokit = Octokit as jest.MockedClass; -const mockedAppAuth = mocked(ghAuth.createGithubAppAuth, { - shallow: false, -}); -const mockedInstallationAuth = mocked(ghAuth.createGithubInstallationAuth, { shallow: false }); -const mockCreateClient = mocked(ghAuth.createOctoClient, { shallow: false }); -const mockListRunners = mocked(listEC2Runners); - -const cleanEnv = process.env; - -const ORG = 'my-org'; - -beforeEach(() => { - nock.disableNetConnect(); - jest.resetModules(); - jest.clearAllMocks(); - process.env = { ...cleanEnv }; - process.env.GITHUB_APP_KEY_BASE64 = 'TEST_CERTIFICATE_DATA'; - process.env.GITHUB_APP_ID = '1337'; - process.env.GITHUB_APP_CLIENT_ID = 'TEST_CLIENT_ID'; - process.env.GITHUB_APP_CLIENT_SECRET = 'TEST_CLIENT_SECRET'; - process.env.RUNNERS_MAXIMUM_COUNT = '3'; - process.env.ENVIRONMENT = 'unit-test-environment'; - process.env.ENABLE_ORGANIZATION_RUNNERS = 'true'; - process.env.LAUNCH_TEMPLATE_NAME = 'lt-1'; - process.env.SUBNET_IDS = 'subnet-123'; - process.env.INSTANCE_TYPES = 'm5.large'; - process.env.INSTANCE_TARGET_CAPACITY_TYPE = 'spot'; - process.env.RUNNER_OWNER = ORG; - - const mockTokenReturnValue = { - data: { - token: '1234abcd', - }, - }; - mockOctokit.actions.createRegistrationTokenForOrg.mockImplementation(() => mockTokenReturnValue); - - mockOctokit.paginate.mockImplementation(() => [ - { - id: 1, - name: 'i-1', - os: 'linux', - status: 'online', - busy: false, - labels: [], - }, - { - id: 2, - name: 'i-2', - os: 'linux', - status: 'online', - busy: true, - labels: [], - }, - { - id: 3, - name: 'i-3', - os: 'linux', - status: 'offline', - busy: false, - labels: [], - }, - { - id: 11, - name: 'j-1', // some runner of another env - os: 'linux', - status: 'online', - busy: false, - labels: [], - }, - { - id: 12, - name: 'j-2', // some runner of another env - os: 'linux', - status: 'online', - busy: true, - labels: [], - }, - ]); - - mockListRunners.mockImplementation(async () => [ - { - instanceId: 'i-1', - launchTime: new Date(), - type: 'Org', - owner: ORG, - }, - { - instanceId: 'i-2', - launchTime: new Date(), - type: 'Org', - owner: ORG, - }, - { - instanceId: 'i-3', - launchTime: new Date(), - type: 'Org', - owner: ORG, - }, - ]); - - const mockInstallationIdReturnValueOrgs = { - data: { - id: 1, - }, - }; - mockOctokit.apps.getOrgInstallation.mockImplementation(() => mockInstallationIdReturnValueOrgs); - - mockedAppAuth.mockResolvedValue({ - type: 'app', - token: 'token', - appId: 1, - expiresAt: 'some-date', - }); - mockedInstallationAuth.mockResolvedValue({ - type: 'token', - tokenType: 'installation', - token: 'token', - createdAt: 'some-date', - expiresAt: 'some-date', - permissions: {}, - repositorySelection: 'all', - installationId: 0, - }); - - mockCreateClient.mockResolvedValue(new mocktokit()); -}); - -describe('Test simple pool.', () => { - describe('With GitHub Cloud', () => { - it('Top up pool with pool size 2.', async () => { - const spy = jest.spyOn(scale, 'createRunners'); - await expect(adjust({ poolSize: 2 })).resolves; - expect(spy).toBeCalled; - }); - - it('Should not top up if pool size is reached.', async () => { - const spy = jest.spyOn(scale, 'createRunners'); - await expect(adjust({ poolSize: 1 })).resolves; - expect(spy).not.toHaveBeenCalled; - }); - }); - - describe('With GHES', () => { - beforeEach(() => { - process.env.GHES_URL = 'https://github.enterprise.something'; - }); - - it('Top up if the pool size is set to 5', async () => { - const spy = jest.spyOn(scale, 'createRunners'); - await expect(adjust({ poolSize: 5 })).resolves; - expect(spy).toBeCalled; - }); - }); -}); diff --git a/modules/runners/lambdas/runners/src/pool/pool.ts b/modules/runners/lambdas/runners/src/pool/pool.ts deleted file mode 100644 index e98200073b..0000000000 --- a/modules/runners/lambdas/runners/src/pool/pool.ts +++ /dev/null @@ -1,101 +0,0 @@ -import yn from 'yn'; - -import { listEC2Runners } from '../aws/runners'; -import { createGithubAppAuth, createGithubInstallationAuth, createOctoClient } from '../gh-auth/gh-auth'; -import { logger as rootLogger } from '../logger'; -import { createRunners } from '../scale-runners/scale-up'; - -const logger = rootLogger.getChildLogger({ name: 'pool' }); - -export interface PoolEvent { - poolSize: number; -} - -export async function adjust(event: PoolEvent): Promise { - logger.info(`Checking current pool size against pool of size: ${event.poolSize}`); - const runnerExtraLabels = process.env.RUNNER_EXTRA_LABELS; - const runnerGroup = process.env.RUNNER_GROUP_NAME; - const environment = process.env.ENVIRONMENT; - const ghesBaseUrl = process.env.GHES_URL; - const subnets = process.env.SUBNET_IDS.split(','); - const instanceTypes = process.env.INSTANCE_TYPES.split(','); - const instanceTargetTargetCapacityType = process.env.INSTANCE_TARGET_CAPACITY_TYPE; - const ephemeral = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false }); - const disableAutoUpdate = yn(process.env.DISABLE_RUNNER_AUTOUPDATE, { default: false }); - const launchTemplateName = process.env.LAUNCH_TEMPLATE_NAME; - const instanceMaxSpotPrice = process.env.INSTANCE_MAX_SPOT_PRICE; - const instanceAllocationStrategy = process.env.INSTANCE_ALLOCATION_STRATEGY || 'lowest-price'; // same as AWS default - const runnerOwner = process.env.RUNNER_OWNER; - - let ghesApiUrl = ''; - if (ghesBaseUrl) { - ghesApiUrl = `${ghesBaseUrl}/api/v3`; - } - - const installationId = await getInstallationId(ghesApiUrl, runnerOwner); - const ghAuth = await createGithubInstallationAuth(installationId, ghesApiUrl); - const githubInstallationClient = await createOctoClient(ghAuth.token, ghesApiUrl); - - // Look up the runners registered in GitHub, could be also non managed by this module. - const runners = await githubInstallationClient.paginate( - githubInstallationClient.actions.listSelfHostedRunnersForOrg, - { - org: runnerOwner, - per_page: 100, - }, - ); - const idleRunners = runners.filter((r) => !r.busy && r.status === 'online').map((r) => r.name); - - // Look up the managed ec2 runners in AWS, but running does not mean idle - const ec2runners = ( - await listEC2Runners({ - environment, - runnerOwner, - runnerType: 'Org', - statuses: ['running'], - }) - ).map((r) => r.instanceId); - - const managedIdleRunners = ec2runners.filter((r) => idleRunners.includes(r)); - const topUp = event.poolSize - managedIdleRunners.length; - if (topUp > 0) { - logger.info(`The pool will be topped up with ${topUp} runners.`); - await createRunners( - { - ephemeral, - ghesBaseUrl, - runnerExtraLabels, - runnerGroup, - runnerOwner, - runnerType: 'Org', - disableAutoUpdate: disableAutoUpdate, - }, - { - ec2instanceCriteria: { - instanceTypes, - targetCapacityType: instanceTargetTargetCapacityType, - maxSpotPrice: instanceMaxSpotPrice, - instanceAllocationStrategy: instanceAllocationStrategy, - }, - environment, - launchTemplateName, - subnets, - numberOfRunners: topUp, - }, - githubInstallationClient, - ); - } else { - logger.info(`Pool will not be topped up. Find ${managedIdleRunners} managed idle runners.`); - } -} - -async function getInstallationId(ghesApiUrl: string, org: string): Promise { - const ghAuth = await createGithubAppAuth(undefined, ghesApiUrl); - const githubClient = await createOctoClient(ghAuth.token, ghesApiUrl); - - return ( - await githubClient.apps.getOrgInstallation({ - org, - }) - ).data.id; -} diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-down.test.ts b/modules/runners/lambdas/runners/src/scale-runners/scale-down.test.ts deleted file mode 100644 index f05d713f41..0000000000 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-down.test.ts +++ /dev/null @@ -1,570 +0,0 @@ -import { Octokit } from '@octokit/rest'; -import { mocked } from 'jest-mock'; -import moment from 'moment'; -import nock from 'nock'; - -import * as ghAuth from '../gh-auth/gh-auth'; -import { RunnerInfo, RunnerList, listEC2Runners, terminateRunner } from './../aws/runners'; -import { githubCache } from './cache'; -import { scaleDown } from './scale-down'; - -const mockOctokit = { - apps: { - getOrgInstallation: jest.fn(), - getRepoInstallation: jest.fn(), - }, - actions: { - listSelfHostedRunnersForRepo: jest.fn(), - listSelfHostedRunnersForOrg: jest.fn(), - deleteSelfHostedRunnerFromOrg: jest.fn(), - deleteSelfHostedRunnerFromRepo: jest.fn(), - getSelfHostedRunnerForOrg: jest.fn(), - getSelfHostedRunnerForRepo: jest.fn(), - }, - paginate: jest.fn(), -}; -jest.mock('@octokit/rest', () => ({ - Octokit: jest.fn().mockImplementation(() => mockOctokit), -})); - -jest.mock('./../aws/runners'); -jest.mock('./../gh-auth/gh-auth'); -jest.mock('./cache'); - -const mocktokit = Octokit as jest.MockedClass; -const mockedAppAuth = mocked(ghAuth.createGithubAppAuth, { shallow: false }); -const mockedInstallationAuth = mocked(ghAuth.createGithubInstallationAuth, { shallow: false }); -const mockCreateClient = mocked(ghAuth.createOctoClient, { shallow: false }); -const mockListRunners = mocked(listEC2Runners); - -export interface TestData { - repositoryName: string; - repositoryOwner: string; -} - -const cleanEnv = process.env; - -const environment = 'unit-test-environment'; -const minimumRunningTimeInMinutes = 15; -const runnerBootTimeInMinutes = 5; -const TEST_DATA: TestData = { - repositoryName: 'hello-world', - repositoryOwner: 'Codertocat', -}; - -let DEFAULT_RUNNERS: RunnerList[]; -let RUNNERS_ALL_REMOVED: RunnerInfo[]; -let DEFAULT_RUNNERS_REPO_TO_BE_REMOVED: RunnerInfo[]; -let RUNNERS_ORG_TO_BE_REMOVED_WITH_AUTO_SCALING_CONFIG: RunnerInfo[]; -let RUNNERS_REPO_WITH_AUTO_SCALING_CONFIG: RunnerInfo[]; -let RUNNERS_ORG_WITH_AUTO_SCALING_CONFIG: RunnerInfo[]; -let DEFAULT_RUNNERS_REPO: RunnerInfo[]; -let DEFAULT_RUNNERS_ORG: RunnerInfo[]; -let DEFAULT_RUNNERS_ORG_TO_BE_REMOVED: RunnerInfo[]; -let DEFAULT_RUNNERS_ORPHANED: RunnerInfo[]; -let DEFAULT_REPO_RUNNERS_ORPHANED: RunnerInfo[]; -let DEFAULT_ORG_RUNNERS_ORPHANED: RunnerInfo[]; -const DEFAULT_RUNNERS_ORIGINAL = [ - { - instanceId: 'i-idle-101', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes + 5, 'minutes') - .toDate(), - type: 'Repo', - owner: `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, - }, - { - instanceId: 'i-idle-102', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes + 3, 'minutes') - .toDate(), - type: 'Org', - owner: TEST_DATA.repositoryOwner, - }, - { - instanceId: 'i-oldest-idle-103', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes + 27, 'minutes') - .toDate(), - type: 'Repo', - owner: `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, - }, - { - instanceId: 'i-oldest-idle-104', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes + 27, 'minutes') - .toDate(), - type: 'Org', - owner: TEST_DATA.repositoryOwner, - }, - { - instanceId: 'i-running-105', - launchTime: moment(new Date()).subtract(25, 'minutes').toDate(), - type: 'Repo', - owner: `doe/another-repo`, - }, - { - instanceId: 'i-running-106', - launchTime: moment(new Date()).subtract(25, 'minutes').toDate(), - type: 'Org', - owner: TEST_DATA.repositoryOwner, - }, - { - instanceId: 'i-orphan-107', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes + 5, 'minutes') - .toDate(), - type: 'Repo', - owner: `doe/another-repo`, - }, - { - instanceId: 'i-not-registered-108', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes - 1, 'minutes') - .toDate(), - type: 'Repo', - owner: `doe/another-repo`, - }, - { - instanceId: 'i-not-registered-109', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes - 2, 'minutes') - .toDate(), - type: 'Org', - owner: TEST_DATA.repositoryOwner, - }, - { - instanceId: 'i-legacy-110', - launchTime: moment(new Date()) - .subtract(minimumRunningTimeInMinutes + 5, 'minutes') - .toDate(), - repo: `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, - }, - { - instanceId: 'i-new-111', - launchTime: moment(new Date()).toDate(), - repo: `${TEST_DATA.repositoryOwner}/${TEST_DATA.repositoryName}`, - }, - { - instanceId: 'i-running-112', - launchTime: moment(new Date()).subtract(25, 'minutes').toDate(), - type: 'Repo', - owner: `doe/another-repo`, - }, - { - instanceId: 'i-running-113', - launchTime: moment(new Date()).subtract(25, 'minutes').toDate(), - type: 'Org', - owner: TEST_DATA.repositoryOwner, - }, -]; - -const DEFAULT_REGISTERED_RUNNERS = [ - { - id: 101, - name: 'i-idle-101', - }, - { - id: 102, - name: 'i-idle-102', - }, - { - id: 103, - name: 'i-oldest-idle-103', - }, - { - id: 104, - name: 'i-oldest-idle-104', - }, - { - id: 105, - name: 'i-running-105', - }, - { - id: 106, - name: 'i-running-106', - }, - { - id: 1121, - name: 'i-running-112-1', - }, - { - id: 1122, - name: 'i-running-112-2', - }, - { - id: 1131, - name: 'i-running-113-1', - }, - { - id: 1132, - name: 'i-running-113-2', - }, -]; - -describe('scaleDown', () => { - beforeEach(() => { - process.env = { ...cleanEnv }; - process.env.GITHUB_APP_KEY_BASE64 = 'TEST_CERTIFICATE_DATA'; - process.env.GITHUB_APP_ID = '1337'; - process.env.GITHUB_APP_CLIENT_ID = 'TEST_CLIENT_ID'; - process.env.GITHUB_APP_CLIENT_SECRET = 'TEST_CLIENT_SECRET'; - process.env.RUNNERS_MAXIMUM_COUNT = '3'; - process.env.SCALE_DOWN_CONFIG = '[]'; - process.env.ENVIRONMENT = environment; - process.env.MINIMUM_RUNNING_TIME_IN_MINUTES = minimumRunningTimeInMinutes.toString(); - process.env.RUNNER_BOOT_TIME_IN_MINUTES = runnerBootTimeInMinutes.toString(); - nock.disableNetConnect(); - jest.clearAllMocks(); - jest.resetModules(); - githubCache.clients.clear(); - githubCache.runners.clear(); - mockOctokit.apps.getOrgInstallation.mockImplementation(() => ({ - data: { - id: 'ORG', - }, - })); - mockOctokit.apps.getRepoInstallation.mockImplementation(() => ({ - data: { - id: 'REPO', - }, - })); - - mockOctokit.paginate.mockResolvedValue(DEFAULT_REGISTERED_RUNNERS); - mockOctokit.actions.deleteSelfHostedRunnerFromRepo.mockImplementation((repo) => { - if (repo.runner_id === 105) { - throw Error(); - } else { - return { status: 204 }; - } - }); - mockOctokit.actions.deleteSelfHostedRunnerFromOrg.mockImplementation((repo) => { - if (repo.runner_id === 106) { - throw Error(); - } else { - return { status: 204 }; - } - }); - - mockOctokit.actions.getSelfHostedRunnerForRepo.mockImplementation((repo) => { - if (repo.runner_id === 1121) { - return { - data: { busy: true }, - }; - } else { - return { - data: { busy: false }, - }; - } - }); - mockOctokit.actions.getSelfHostedRunnerForOrg.mockImplementation((repo) => { - if (repo.runner_id === 1131) { - return { - data: { busy: true }, - }; - } else { - return { - data: { busy: false }, - }; - } - }); - - const mockTerminateRunners = mocked(terminateRunner); - mockTerminateRunners.mockImplementation(async () => { - return; - }); - mockedAppAuth.mockResolvedValue({ - type: 'app', - token: 'token', - appId: 1, - expiresAt: 'some-date', - }); - mockedInstallationAuth.mockResolvedValue({ - type: 'token', - tokenType: 'installation', - token: 'token', - createdAt: 'some-date', - expiresAt: 'some-date', - permissions: {}, - repositorySelection: 'all', - installationId: 0, - }); - mockCreateClient.mockResolvedValue(new mocktokit()); - DEFAULT_RUNNERS = JSON.parse(JSON.stringify(DEFAULT_RUNNERS_ORIGINAL)); - DEFAULT_RUNNERS_REPO = DEFAULT_RUNNERS.filter((r) => r.type === 'Repo') as RunnerInfo[]; - DEFAULT_RUNNERS_ORG = DEFAULT_RUNNERS.filter((r) => r.type === 'Org') as RunnerInfo[]; - DEFAULT_RUNNERS_REPO_TO_BE_REMOVED = DEFAULT_RUNNERS_REPO.filter( - (r) => r.instanceId.includes('idle') || r.instanceId.includes('orphan'), - ); - DEFAULT_RUNNERS_ORG_TO_BE_REMOVED = DEFAULT_RUNNERS_ORG.filter( - (r) => r.instanceId.includes('idle') || r.instanceId.includes('orphan'), - ); - - RUNNERS_REPO_WITH_AUTO_SCALING_CONFIG = DEFAULT_RUNNERS_REPO.filter( - (r) => r.instanceId.includes('idle') || r.instanceId.includes('running'), - ); - - RUNNERS_ORG_WITH_AUTO_SCALING_CONFIG = DEFAULT_RUNNERS_ORG.filter( - (r) => r.instanceId.includes('idle') || r.instanceId.includes('running'), - ); - - RUNNERS_ORG_TO_BE_REMOVED_WITH_AUTO_SCALING_CONFIG = DEFAULT_RUNNERS_ORG.filter((r) => - r.instanceId.includes('oldest'), - ); - - RUNNERS_ALL_REMOVED = DEFAULT_RUNNERS_ORG.filter( - (r) => !r.instanceId.includes('running') && !r.instanceId.includes('registered'), - ); - DEFAULT_RUNNERS_ORPHANED = DEFAULT_RUNNERS_ORIGINAL.filter( - (r) => r.instanceId.includes('orphan') && !r.instanceId.includes('not-registered'), - ) as RunnerInfo[]; - DEFAULT_REPO_RUNNERS_ORPHANED = DEFAULT_RUNNERS_REPO.filter( - (r) => r.instanceId.includes('orphan') && !r.instanceId.includes('not-registered'), - ); - DEFAULT_ORG_RUNNERS_ORPHANED = DEFAULT_RUNNERS_ORG.filter( - (r) => r.instanceId.includes('orphan') && !r.instanceId.includes('not-registered'), - ); - }); - - describe('github.com', () => { - describe('no runners running', () => { - beforeEach(() => { - mockListRunners.mockResolvedValue([]); - }); - - it('No runners online', async () => { - await scaleDown(); - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - expect(terminateRunner).not; - expect(mockOctokit.apps.getRepoInstallation).not; - expect(mockOctokit.apps.getRepoInstallation).not; - }); - }); - - it('Terminates 3 of 5 runners owned by repos and all orphaned', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS_REPO); - await scaleDown(); - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getRepoInstallation).toBeCalled(); - - expect(terminateRunner).toBeCalledTimes(4); - for (const toTerminate of DEFAULT_RUNNERS_REPO_TO_BE_REMOVED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - for (const toTerminate of DEFAULT_REPO_RUNNERS_ORPHANED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - - it('Terminates 2 of 3 runners owned by orgs and all orphaned', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS_ORG); - await scaleDown(); - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getOrgInstallation).toBeCalled(); - expect(terminateRunner).toBeCalledTimes(3); - for (const toTerminate of DEFAULT_RUNNERS_ORG_TO_BE_REMOVED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - for (const toTerminate of DEFAULT_ORG_RUNNERS_ORPHANED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - - describe('With idle config', () => { - beforeEach(() => { - process.env.SCALE_DOWN_CONFIG = JSON.stringify([ - { - idleCount: 3, - cron: '* * * * * *', - timeZone: 'Europe/Amsterdam', - }, - ]); - }); - - it('Terminates 1 runner owned by orgs', async () => { - mockListRunners.mockResolvedValue(RUNNERS_ORG_WITH_AUTO_SCALING_CONFIG); - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getOrgInstallation).toBeCalled(); - expect(terminateRunner).toBeCalledTimes(1); - for (const toTerminate of RUNNERS_ORG_TO_BE_REMOVED_WITH_AUTO_SCALING_CONFIG) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - - it('Terminates 0 runners owned by org', async () => { - mockListRunners.mockResolvedValue(RUNNERS_REPO_WITH_AUTO_SCALING_CONFIG); - process.env.ENABLE_ORGANIZATION_RUNNERS = 'false'; - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getRepoInstallation).toBeCalled(); - expect(terminateRunner).not.toBeCalled(); - }); - }); - - it('No instances terminates when delete runner in github results in a non 204 status.', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS); - mockOctokit.actions.deleteSelfHostedRunnerFromOrg.mockImplementation(() => { - return { status: 500 }; - }); - - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getOrgInstallation).toBeCalled(); - expect(terminateRunner).not.toBeCalled; - }); - - it('Terminates 6 runners amongst all owners and all orphaned', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS); - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getRepoInstallation).toBeCalledTimes(2); - expect(mockOctokit.apps.getOrgInstallation).toBeCalledTimes(1); - expect(terminateRunner).toBeCalledTimes(8); - for (const toTerminate of RUNNERS_ALL_REMOVED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - for (const toTerminate of DEFAULT_RUNNERS_ORPHANED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - }); - - describe('ghes', () => { - beforeEach(() => { - process.env.GHES_URL = 'https://github.enterprise.something'; - }); - describe('no runners running', () => { - beforeEach(() => { - mockListRunners.mockResolvedValue([]); - }); - - it('No runners online', async () => { - await scaleDown(); - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - expect(terminateRunner).not; - expect(mockOctokit.apps.getRepoInstallation).not; - expect(mockOctokit.apps.getRepoInstallation).not; - }); - }); - - it('Terminates 3 of 5 runners owned by repos and all orphaned', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS_REPO); - await scaleDown(); - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getRepoInstallation).toBeCalled(); - expect(terminateRunner).toBeCalledTimes(4); - for (const toTerminate of DEFAULT_RUNNERS_REPO_TO_BE_REMOVED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - for (const toTerminate of DEFAULT_REPO_RUNNERS_ORPHANED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - - it('Terminates 2 of 3 runners owned by orgs and all orphaned', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS_ORG); - await scaleDown(); - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getOrgInstallation).toBeCalled(); - expect(terminateRunner).toBeCalledTimes(3); - for (const toTerminate of DEFAULT_RUNNERS_ORG_TO_BE_REMOVED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - for (const toTerminate of DEFAULT_ORG_RUNNERS_ORPHANED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - - describe('With idle config', () => { - beforeEach(() => { - process.env.SCALE_DOWN_CONFIG = JSON.stringify([ - { - idleCount: 3, - cron: '* * * * * *', - timeZone: 'Europe/Amsterdam', - }, - ]); - }); - - it('Terminates 1 runner owned by orgs', async () => { - mockListRunners.mockResolvedValue(RUNNERS_ORG_WITH_AUTO_SCALING_CONFIG); - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getOrgInstallation).toBeCalled(); - expect(terminateRunner).toBeCalledTimes(1); - for (const toTerminate of RUNNERS_ORG_TO_BE_REMOVED_WITH_AUTO_SCALING_CONFIG) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - - it('Terminates 0 runners owned by repos', async () => { - mockListRunners.mockResolvedValue(RUNNERS_REPO_WITH_AUTO_SCALING_CONFIG); - process.env.ENABLE_ORGANIZATION_RUNNERS = 'false'; - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getRepoInstallation).toBeCalled(); - expect(terminateRunner).not.toBeCalled(); - }); - }); - - it('Terminates 6 runners amongst all owners and all orphaned', async () => { - mockListRunners.mockResolvedValue(DEFAULT_RUNNERS); - await scaleDown(); - - expect(listEC2Runners).toBeCalledWith({ - environment: environment, - }); - - expect(mockOctokit.apps.getRepoInstallation).toBeCalledTimes(2); - expect(mockOctokit.apps.getOrgInstallation).toBeCalledTimes(1); - expect(terminateRunner).toBeCalledTimes(8); - for (const toTerminate of RUNNERS_ALL_REMOVED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - for (const toTerminate of DEFAULT_RUNNERS_ORPHANED) { - expect(terminateRunner).toHaveBeenCalledWith(toTerminate.instanceId); - } - }); - }); -}); diff --git a/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts b/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts deleted file mode 100644 index c0127b906b..0000000000 --- a/modules/runners/lambdas/runners/src/scale-runners/scale-up.ts +++ /dev/null @@ -1,238 +0,0 @@ -import { Octokit } from '@octokit/rest'; -import yn from 'yn'; - -import { createGithubAppAuth, createGithubInstallationAuth, createOctoClient } from '../gh-auth/gh-auth'; -import { LogFields, logger as rootLogger } from '../logger'; -import { RunnerInputParameters, createRunner, listEC2Runners } from './../aws/runners'; -import ScaleError from './ScaleError'; - -const logger = rootLogger.getChildLogger({ name: 'scale-up' }); - -export interface ActionRequestMessage { - id: number; - eventType: 'check_run' | 'workflow_job'; - repositoryName: string; - repositoryOwner: string; - installationId: number; -} - -interface CreateGitHubRunnerConfig { - ephemeral: boolean; - ghesBaseUrl: string; - runnerExtraLabels: string | undefined; - runnerGroup: string | undefined; - runnerOwner: string; - runnerType: 'Org' | 'Repo'; - disableAutoUpdate: boolean; -} - -interface CreateEC2RunnerConfig { - environment: string; - subnets: string[]; - launchTemplateName: string; - ec2instanceCriteria: RunnerInputParameters['ec2instanceCriteria']; - numberOfRunners?: number; - amiIdSsmParameterName?: string; -} - -function generateRunnerServiceConfig(githubRunnerConfig: CreateGitHubRunnerConfig, token: string) { - const config = [ - `--url ${githubRunnerConfig.ghesBaseUrl ?? 'https://github.com'}/${githubRunnerConfig.runnerOwner}`, - `--token ${token}`, - ]; - - if (githubRunnerConfig.runnerExtraLabels !== undefined) { - config.push(`--labels ${githubRunnerConfig.runnerExtraLabels}`); - } - - if (githubRunnerConfig.ephemeral) { - config.push(`--ephemeral`); - } - - if (githubRunnerConfig.disableAutoUpdate) { - config.push('--disableupdate'); - } - - if (githubRunnerConfig.runnerType === 'Org' && githubRunnerConfig.runnerGroup !== undefined) { - config.push(`--runnergroup ${githubRunnerConfig.runnerGroup}`); - } - - return config; -} - -async function getGithubRunnerRegistrationToken(githubRunnerConfig: CreateGitHubRunnerConfig, ghClient: Octokit) { - const registrationToken = - githubRunnerConfig.runnerType === 'Org' - ? await ghClient.actions.createRegistrationTokenForOrg({ org: githubRunnerConfig.runnerOwner }) - : await ghClient.actions.createRegistrationTokenForRepo({ - owner: githubRunnerConfig.runnerOwner.split('/')[0], - repo: githubRunnerConfig.runnerOwner.split('/')[1], - }); - return registrationToken.data.token; -} - -async function getInstallationId( - ghesApiUrl: string, - enableOrgLevel: boolean, - payload: ActionRequestMessage, -): Promise { - if (payload.installationId !== 0) { - return payload.installationId; - } - - const ghAuth = await createGithubAppAuth(undefined, ghesApiUrl); - const githubClient = await createOctoClient(ghAuth.token, ghesApiUrl); - return enableOrgLevel - ? ( - await githubClient.apps.getOrgInstallation({ - org: payload.repositoryOwner, - }) - ).data.id - : ( - await githubClient.apps.getRepoInstallation({ - owner: payload.repositoryOwner, - repo: payload.repositoryName, - }) - ).data.id; -} - -async function isJobQueued(githubInstallationClient: Octokit, payload: ActionRequestMessage): Promise { - let isQueued = false; - if (payload.eventType === 'workflow_job') { - const jobForWorkflowRun = await githubInstallationClient.actions.getJobForWorkflowRun({ - job_id: payload.id, - owner: payload.repositoryOwner, - repo: payload.repositoryName, - }); - isQueued = jobForWorkflowRun.data.status === 'queued'; - } else if (payload.eventType === 'check_run') { - const checkRun = await githubInstallationClient.checks.get({ - check_run_id: payload.id, - owner: payload.repositoryOwner, - repo: payload.repositoryName, - }); - isQueued = checkRun.data.status === 'queued'; - } else { - throw Error(`Event ${payload.eventType} is not supported`); - } - if (!isQueued) { - logger.info(`Job not queued`, LogFields.print()); - } - return isQueued; -} - -export async function createRunners( - githubRunnerConfig: CreateGitHubRunnerConfig, - ec2RunnerConfig: CreateEC2RunnerConfig, - ghClient: Octokit, -): Promise { - const token = await getGithubRunnerRegistrationToken(githubRunnerConfig, ghClient); - - const runnerServiceConfig = generateRunnerServiceConfig(githubRunnerConfig, token); - - await createRunner({ - runnerServiceConfig, - runnerType: githubRunnerConfig.runnerType, - runnerOwner: githubRunnerConfig.runnerOwner, - ...ec2RunnerConfig, - }); -} - -export async function scaleUp(eventSource: string, payload: ActionRequestMessage): Promise { - logger.info( - `Received ${payload.eventType} from ${payload.repositoryOwner}/${payload.repositoryName}`, - LogFields.print(), - ); - - if (eventSource !== 'aws:sqs') throw Error('Cannot handle non-SQS events!'); - const enableOrgLevel = yn(process.env.ENABLE_ORGANIZATION_RUNNERS, { default: true }); - const maximumRunners = parseInt(process.env.RUNNERS_MAXIMUM_COUNT || '3'); - const runnerExtraLabels = process.env.RUNNER_EXTRA_LABELS; - const runnerGroup = process.env.RUNNER_GROUP_NAME; - const environment = process.env.ENVIRONMENT; - const ghesBaseUrl = process.env.GHES_URL; - const subnets = process.env.SUBNET_IDS.split(','); - const instanceTypes = process.env.INSTANCE_TYPES.split(','); - const instanceTargetTargetCapacityType = process.env.INSTANCE_TARGET_CAPACITY_TYPE; - const ephemeralEnabled = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false }); - const disableAutoUpdate = yn(process.env.DISABLE_RUNNER_AUTOUPDATE, { default: false }); - const launchTemplateName = process.env.LAUNCH_TEMPLATE_NAME; - const instanceMaxSpotPrice = process.env.INSTANCE_MAX_SPOT_PRICE; - const instanceAllocationStrategy = process.env.INSTANCE_ALLOCATION_STRATEGY || 'lowest-price'; // same as AWS default - const enableJobQueuedCheck = yn(process.env.ENABLE_JOB_QUEUED_CHECK, { default: true }); - const amiIdSsmParameterName = process.env.AMI_ID_SSM_PARAMETER_NAME; - - if (ephemeralEnabled && payload.eventType !== 'workflow_job') { - logger.warn( - `${payload.eventType} event is not supported in combination with ephemeral runners.`, - LogFields.print(), - ); - throw Error( - `The event type ${payload.eventType} is not supported in combination with ephemeral runners.` + - `Please ensure you have enabled workflow_job events.`, - ); - } - const ephemeral = ephemeralEnabled && payload.eventType === 'workflow_job'; - const runnerType = enableOrgLevel ? 'Org' : 'Repo'; - const runnerOwner = enableOrgLevel ? payload.repositoryOwner : `${payload.repositoryOwner}/${payload.repositoryName}`; - - LogFields.fields = {}; - LogFields.fields.runnerType = runnerType; - LogFields.fields.runnerOwner = runnerOwner; - LogFields.fields.event = payload.eventType; - LogFields.fields.id = payload.id.toString(); - - logger.info(`Received event`, LogFields.print()); - - let ghesApiUrl = ''; - if (ghesBaseUrl) { - ghesApiUrl = `${ghesBaseUrl}/api/v3`; - } - - const installationId = await getInstallationId(ghesApiUrl, enableOrgLevel, payload); - const ghAuth = await createGithubInstallationAuth(installationId, ghesApiUrl); - const githubInstallationClient = await createOctoClient(ghAuth.token, ghesApiUrl); - - if (!enableJobQueuedCheck || (await isJobQueued(githubInstallationClient, payload))) { - const currentRunners = await listEC2Runners({ - environment, - runnerType, - runnerOwner, - }); - logger.info(`Current runners: ${currentRunners.length} of ${maximumRunners}`, LogFields.print()); - - if (currentRunners.length < maximumRunners) { - logger.info(`Attempting to launch a new runner`, LogFields.print()); - - await createRunners( - { - ephemeral, - ghesBaseUrl, - runnerExtraLabels, - runnerGroup, - runnerOwner, - runnerType, - disableAutoUpdate, - }, - { - ec2instanceCriteria: { - instanceTypes, - targetCapacityType: instanceTargetTargetCapacityType, - maxSpotPrice: instanceMaxSpotPrice, - instanceAllocationStrategy: instanceAllocationStrategy, - }, - environment, - launchTemplateName, - subnets, - amiIdSsmParameterName, - }, - githubInstallationClient, - ); - } else { - logger.info('No runner will be created, maximum number of runners reached.', LogFields.print()); - if (ephemeral) { - throw new ScaleError('No runners create: maximum of runners reached.'); - } - } - } -} diff --git a/modules/runners/lambdas/runners/tsconfig.json b/modules/runners/lambdas/runners/tsconfig.json deleted file mode 100644 index eab8079cbb..0000000000 --- a/modules/runners/lambdas/runners/tsconfig.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "compilerOptions": { - /* Basic Options */ - "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, - "outDir": "build", - "lib": [ - "es2020", - "DOM" - ] /* Specify library files to be included in the compilation. */, - "allowJs": true /* Allow javascript files to be compiled. */, - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "./", /* Redirect output structure to the directory. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "incremental": true, /* Enable incremental compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - /* Module Resolution Options */ - "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [] /* List of folders to include type definitions from. */, - // "types": [] /* Type declaration files to be included in compilation. */, - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - /* Experimental Options */ - "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, - "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "resolveJsonModule": true, - "sourceMap": true - }, - "include": [ - "src/**/*" - ], - // required to process types defined in module.d.ts - "ts-node": { - "files": true - } -} \ No newline at end of file diff --git a/modules/runners/lambdas/runners/yarn.lock b/modules/runners/lambdas/runners/yarn.lock deleted file mode 100644 index 3d98abc98b..0000000000 --- a/modules/runners/lambdas/runners/yarn.lock +++ /dev/null @@ -1,5005 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@aws-crypto/ie11-detection@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz#bb6c2facf8f03457e949dcf0921477397ffa4c6e" - integrity sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA== - dependencies: - tslib "^1.11.1" - -"@aws-crypto/sha256-browser@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-2.0.0.tgz#741c9024df55ec59b51e5b1f5d806a4852699fb5" - integrity sha512-rYXOQ8BFOaqMEHJrLHul/25ckWH6GTJtdLSajhlqGMx0PmSueAuvboCuZCTqEKlxR8CQOwRarxYMZZSYlhRA1A== - dependencies: - "@aws-crypto/ie11-detection" "^2.0.0" - "@aws-crypto/sha256-js" "^2.0.0" - "@aws-crypto/supports-web-crypto" "^2.0.0" - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-2.0.0.tgz#f1f936039bdebd0b9e2dd834d65afdc2aac4efcb" - integrity sha512-VZY+mCY4Nmrs5WGfitmNqXzaE873fcIZDu54cbaDaaamsaTOP1DBImV9F4pICc3EHjQXujyE8jig+PFCaew9ig== - dependencies: - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-2.0.1.tgz#79e1e6cf61f652ef2089c08d471c722ecf1626a9" - integrity sha512-mbHTBSPBvg6o/mN/c18Z/zifM05eJrapj5ggoOIeHIWckvkv5VgGi7r/wYpt+QAO2ySKXLNvH2d8L7bne4xrMQ== - dependencies: - "@aws-crypto/util" "^2.0.1" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/supports-web-crypto@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz#fd6cde30b88f77d5a4f57b2c37c560d918014f9e" - integrity sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA== - dependencies: - tslib "^1.11.1" - -"@aws-crypto/util@^2.0.0", "@aws-crypto/util@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-2.0.1.tgz#976cf619cf85084ca85ec5eb947a6ac6b8b5c98c" - integrity sha512-JJmFFwvbm08lULw4Nm5QOLg8+lAQeC8aCXK5xrtxntYzYXCGfHwUJ4Is3770Q7HmICsXthGQ+ZsDL7C2uH3yBQ== - dependencies: - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-sdk/abort-controller@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.226.0.tgz#3adffb8ee5af57ddb154e8544a8eeec76ad32271" - integrity sha512-cJVzr1xxPBd08voknXvR0RLgtZKGKt6WyDpH/BaPCu3rfSqWCDZKzwqe940eqosjmKrxC6pUZNKASIqHOQ8xxQ== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/client-ssm@^3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.238.0.tgz#238863d6e2cf1fde0da241c8eaf70ea88682443b" - integrity sha512-pHsRbaeoa2V3ck0KL5f9538UQrIF1WEjH1x2kyn/cRyU/fEvSTLJQwf2CL2qMl8CBTuWu/Zn1FlKHgWB7h05VA== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.238.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/credential-provider-node" "3.238.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-signing" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - "@aws-sdk/util-waiter" "3.226.0" - tslib "^2.3.1" - uuid "^8.3.2" - -"@aws-sdk/client-sso-oidc@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.238.0.tgz#95aa2e993b6bff2adc74d1821241f80f9ea5b283" - integrity sha512-kazcA2Kp+cXQRtaZi5/T5YFfU9J3nzu1tXJsh0xAm+J3S9LS1ertY1bSX6KBed2xuxx2mfum8JRqli0TJad/pA== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/client-sso@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.238.0.tgz#dcb4df1e97e6e8821f473e70eee81a8d4424664f" - integrity sha512-KHJJWP7hBDa9KLYiU5+hOb+3AAba93PhWebXkpKyQ/Bs+e7ECCreyLCwuME6uWTV01NDuFDpwZ6zUMpyNIcP6Q== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/client-sts@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.238.0.tgz#b814c2cf888cf99be199c25ede851dfcc8ae5ec6" - integrity sha512-jQNwHqxWUGvWCN4o8KUFYQES8r41Oobu7x1KZOMrPhPxy27FUcDjBq/h85VoD2/AZlETSCZLiCnKV3KBh5pT5w== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/credential-provider-node" "3.238.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-sdk-sts" "3.226.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-signing" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - fast-xml-parser "4.0.11" - tslib "^2.3.1" - -"@aws-sdk/config-resolver@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.234.0.tgz#29d8936b713b7ee59b26b335d4f6715d644fc089" - integrity sha512-uZxy4wzllfvgCQxVc+Iqhde0NGAnfmV2hWR6ejadJaAFTuYNvQiRg9IqJy3pkyDPqXySiJ8Bom5PoJfgn55J/A== - dependencies: - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-config-provider" "3.208.0" - "@aws-sdk/util-middleware" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-env@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.226.0.tgz#0bcb89a9abc166b3a48f5c255b9fcabc4cb80daf" - integrity sha512-sd8uK1ojbXxaZXlthzw/VXZwCPUtU3PjObOfr3Evj7MPIM2IH8h29foOlggx939MdLQGboJf9gKvLlvKDWtJRA== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-imds@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.226.0.tgz#0a4558449eb261412b0490ea1c3242eb91659759" - integrity sha512-//z/COQm2AjYFI1Lb0wKHTQSrvLFTyuKLFQGPJsKS7DPoxGOCKB7hmYerlbl01IDoCxTdyL//TyyPxbZEOQD5Q== - dependencies: - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-ini@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.238.0.tgz#ff21f2a52c9867c34814c1548e8d2bd5f5dfb15a" - integrity sha512-WmPNtIYyUasjV7VQxvPNq7ihmx0vFsiKAtjNjjakdrt5TPoma4nUYb9tIG9SuG+kcp4DJIgRLJAgZtXbCcVimg== - dependencies: - "@aws-sdk/credential-provider-env" "3.226.0" - "@aws-sdk/credential-provider-imds" "3.226.0" - "@aws-sdk/credential-provider-process" "3.226.0" - "@aws-sdk/credential-provider-sso" "3.238.0" - "@aws-sdk/credential-provider-web-identity" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-node@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.238.0.tgz#cccd15fc5f8babb843fab7ec3b09b36d40a02c61" - integrity sha512-/RN5EyGfgdIIJdFzv+O0nSaHX1/F3anQjTIBeVg8GJ+82m+bDxMdALsG+NzkYnLilN9Uhc1lSNjLBCoPa5DSEg== - dependencies: - "@aws-sdk/credential-provider-env" "3.226.0" - "@aws-sdk/credential-provider-imds" "3.226.0" - "@aws-sdk/credential-provider-ini" "3.238.0" - "@aws-sdk/credential-provider-process" "3.226.0" - "@aws-sdk/credential-provider-sso" "3.238.0" - "@aws-sdk/credential-provider-web-identity" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-process@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.226.0.tgz#bcd73a6d31d1b3181917d56e54aacbee242b077f" - integrity sha512-iUDMdnrTvbvaCFhWwqyXrhvQ9+ojPqPqXhwZtY1X/Qaz+73S9gXBPJHZaZb2Ke0yKE1Ql3bJbKvmmxC/qLQMng== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-sso@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.238.0.tgz#3e99252faa3e8e8d86e2f0dc8e29813d96f570c2" - integrity sha512-i70V4bFlCVYey3QARJ6XxKEg/4YuoFRnePV2oK37UHOGpEn49uXKwVZqLjzJgFHln7BPlC06cWDqrHUQIMvYrQ== - dependencies: - "@aws-sdk/client-sso" "3.238.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/token-providers" "3.238.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-web-identity@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.226.0.tgz#2b7d20f93a40e2243c7e3857f54b103d19a946fb" - integrity sha512-CCpv847rLB0SFOHz2igvUMFAzeT2fD3YnY4C8jltuJoEkn0ITn1Hlgt13nTJ5BUuvyti2mvyXZHmNzhMIMrIlw== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/fetch-http-handler@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.226.0.tgz#350f78fc18fe9cb0a889ef4870838a8fcfa8855c" - integrity sha512-JewZPMNEBXfi1xVnRa7pVtK/zgZD8/lQ/YnD8pq79WuMa2cwyhDtr8oqCoqsPW+WJT5ScXoMtuHxN78l8eKWgg== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/querystring-builder" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/hash-node@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.226.0.tgz#252d98bcbb1e13c8f26d9d416db03cf8cceac185" - integrity sha512-MdlJhJ9/Espwd0+gUXdZRsHuostB2WxEVAszWxobP0FTT9PnicqnfK7ExmW+DUAc0ywxtEbR3e0UND65rlSTVw== - dependencies: - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-buffer-from" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/invalid-dependency@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.226.0.tgz#74586f60859ed1813985e3d642066cc46d2e9d40" - integrity sha512-QXOYFmap8g9QzRjumcRCIo2GEZkdCwd7ePQW0OABWPhKHzlJ74vvBxywjU3s39EEBEluWXtZ7Iufg6GxZM4ifw== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/is-array-buffer@3.201.0": - version "3.201.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz#06e557adc284fac2f26071c2944ae01f61b95854" - integrity sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/middleware-content-length@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.226.0.tgz#6cc952049f6e3cdc3a3778c9dce9f2aee942b5fe" - integrity sha512-ksUzlHJN2JMuyavjA46a4sctvnrnITqt2tbGGWWrAuXY1mel2j+VbgnmJUiwHKUO6bTFBBeft5Vd1TSOb4JmiA== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-endpoint@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.226.0.tgz#d776480be4b5a9534c2805b7425be05497f840b7" - integrity sha512-EvLFafjtUxTT0AC9p3aBQu1/fjhWdIeK58jIXaNFONfZ3F8QbEYUPuF/SqZvJM6cWfOO9qwYKkRDbCSTYhprIg== - dependencies: - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-config-provider" "3.208.0" - "@aws-sdk/util-middleware" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-host-header@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.226.0.tgz#1e1ecb034929e0dbc532ae501fd93781438f9a24" - integrity sha512-haVkWVh6BUPwKgWwkL6sDvTkcZWvJjv8AgC8jiQuSl8GLZdzHTB8Qhi3IsfFta9HAuoLjxheWBE5Z/L0UrfhLA== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-logger@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.226.0.tgz#37fd0e62f555befd526b03748c3aab60dcefecf3" - integrity sha512-m9gtLrrYnpN6yckcQ09rV7ExWOLMuq8mMPF/K3DbL/YL0TuILu9i2T1W+JuxSX+K9FMG2HrLAKivE/kMLr55xA== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-recursion-detection@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.226.0.tgz#e149b9138e94d2fa70e7752ba6b1ccb537009706" - integrity sha512-mwRbdKEUeuNH5TEkyZ5FWxp6bL2UC1WbY+LDv6YjHxmSMKpAoOueEdtU34PqDOLrpXXxIGHDFmjeGeMfktyEcA== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-retry@3.235.0": - version "3.235.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.235.0.tgz#c0d938db85a771812204ed5e981eaf5eef6b580b" - integrity sha512-50WHbJGpD3SNp9763MAlHqIhXil++JdQbKejNpHg7HsJne/ao3ub+fDOfx//mMBjpzBV25BGd5UlfL6blrClSg== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/service-error-classification" "3.229.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-middleware" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - tslib "^2.3.1" - uuid "^8.3.2" - -"@aws-sdk/middleware-sdk-sts@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.226.0.tgz#e8a8cf42bba8963259546120cde1e408628863f9" - integrity sha512-NN9T/qoSD1kZvAT+VLny3NnlqgylYQcsgV3rvi/8lYzw/G/2s8VS6sm/VTWGGZhx08wZRv20MWzYu3bftcyqUg== - dependencies: - "@aws-sdk/middleware-signing" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-serde@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.226.0.tgz#c837ef33b34bec2af19a1c177a0c02a1ae20da5e" - integrity sha512-nPuOOAkSfx9TxzdKFx0X2bDlinOxGrqD7iof926K/AEflxGD1DBdcaDdjlYlPDW2CVE8LV/rAgbYuLxh/E/1VA== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-signing@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.226.0.tgz#ebb1d142ac2767466f2e464bb7dba9837143b4d1" - integrity sha512-E6HmtPcl+IjYDDzi1xI2HpCbBq2avNWcjvCriMZWuTAtRVpnA6XDDGW5GY85IfS3A8G8vuWqEVPr8JcYUcjfew== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-middleware" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-stack@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.226.0.tgz#b0408370270188103987c457c758f9cf7651754f" - integrity sha512-85wF29LvPvpoed60fZGDYLwv1Zpd/cM0C22WSSFPw1SSJeqO4gtFYyCg2squfT3KI6kF43IIkOCJ+L7GtryPug== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/middleware-user-agent@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.226.0.tgz#26653189f3e8da86514f77688a80d0ad445c0799" - integrity sha512-N1WnfzCW1Y5yWhVAphf8OPGTe8Df3vmV7/LdsoQfmpkCZgLZeK2o0xITkUQhRj1mbw7yp8tVFLFV3R2lMurdAQ== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/node-config-provider@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.226.0.tgz#a9e21512ef824142bb928a0b2f85b39a75b8964d" - integrity sha512-B8lQDqiRk7X5izFEUMXmi8CZLOKCTWQJU9HQf3ako+sF0gexo4nHN3jhoRWyLtcgC5S3on/2jxpAcqtm7kuY3w== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/node-http-handler@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.226.0.tgz#373886e949d214a99a3521bd6c141fa17b0e89fe" - integrity sha512-xQCddnZNMiPmjr3W7HYM+f5ir4VfxgJh37eqZwX6EZmyItFpNNeVzKUgA920ka1VPz/ZUYB+2OFGiX3LCLkkaA== - dependencies: - "@aws-sdk/abort-controller" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/querystring-builder" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/property-provider@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.226.0.tgz#ef0ff37c319dc37a52f08fa7544f861308a3bbd8" - integrity sha512-TsljjG+Sg0LmdgfiAlWohluWKnxB/k8xenjeozZfzOr5bHmNHtdbWv6BtNvD/R83hw7SFXxbJHlD5H4u9p2NFg== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/protocol-http@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.226.0.tgz#0af7bdc331508e556b722aad0cb78eefa93466e3" - integrity sha512-zWkVqiTA9RXL6y0hhfZc9bcU4DX2NI6Hw9IhQmSPeM59mdbPjJlY4bLlMr5YxywqO3yQ/ylNoAfrEzrDjlOSRg== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/querystring-builder@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.226.0.tgz#11cd751abeac66f1f9349225454bac3e39808926" - integrity sha512-LVurypuNeotO4lmirKXRC4NYrZRAyMJXuwO0f2a5ZAUJCjauwYrifKue6yCfU7bls7gut7nfcR6B99WBYpHs3g== - dependencies: - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-uri-escape" "3.201.0" - tslib "^2.3.1" - -"@aws-sdk/querystring-parser@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.226.0.tgz#ba6a26727c98d46c95180e6cdc463039c5e4740d" - integrity sha512-FzB+VrQ47KAFxiPt2YXrKZ8AOLZQqGTLCKHzx4bjxGmwgsjV8yIbtJiJhZLMcUQV4LtGeIY9ixIqQhGvnZHE4A== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/service-error-classification@3.229.0": - version "3.229.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.229.0.tgz#768f1eb92775ca2cc99c6451a2303a0008a28fc1" - integrity sha512-dnzWWQ0/NoWMUZ5C0DW3dPm0wC1O76Y/SpKbuJzWPkx1EYy6r8p32Ly4D9vUzrKDbRGf48YHIF2kOkBmu21CLg== - -"@aws-sdk/shared-ini-file-loader@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.226.0.tgz#d0ade86834b1803ce4b9dcab459e57e0376fd6cf" - integrity sha512-661VQefsARxVyyV2FX9V61V+nNgImk7aN2hYlFKla6BCwZfMng+dEtD0xVGyg1PfRw0qvEv5LQyxMVgHcUSevA== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/signature-v4@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.226.0.tgz#100390b5c5b55a9b0abd05b06fceb36cfa0ecf98" - integrity sha512-/R5q5agdPd7HJB68XMzpxrNPk158EHUvkFkuRu5Qf3kkkHebEzWEBlWoVpUe6ss4rP9Tqcue6xPuaftEmhjpYw== - dependencies: - "@aws-sdk/is-array-buffer" "3.201.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-hex-encoding" "3.201.0" - "@aws-sdk/util-middleware" "3.226.0" - "@aws-sdk/util-uri-escape" "3.201.0" - tslib "^2.3.1" - -"@aws-sdk/smithy-client@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.234.0.tgz#8f0021e021f0e52730ed0a8f271f839eb63bc374" - integrity sha512-8AtR/k4vsFvjXeQbIzq/Wy7Nbk48Ou0wUEeVYPHWHPSU8QamFWORkOwmKtKMfHAyZvmqiAPeQqHFkq+UJhWyyQ== - dependencies: - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/token-providers@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.238.0.tgz#825306e82f24276e6aaa4850f36bba87418ba485" - integrity sha512-vYUwmy0kTzA99mJCVvad+/5RDlWve/xxnppT8DJK3JIdAgskp+rULY+joVnq2NSl489UAioUnFGs57vUxi8Pog== - dependencies: - "@aws-sdk/client-sso-oidc" "3.238.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/types@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.226.0.tgz#3dba2ba223fbb8ac1ebc84de0e036ce69a81d469" - integrity sha512-MmmNHrWeO4man7wpOwrAhXlevqtOV9ZLcH4RhnG5LmRce0RFOApx24HoKENfFCcOyCm5LQBlsXCqi0dZWDWU0A== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/types@^3.1.0": - version "3.215.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.215.0.tgz#72a595e2c1a5c8c3f0291bccf71d481412b1843b" - integrity sha512-eRbCVjwzTYd9C5e2mceScJ6D2kYDDEC3PLkYfJa+1wH9iiF2JlbiYozAokyeYBHQ+AjmD93MK58RBoM8iZfH0Q== - -"@aws-sdk/url-parser@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.226.0.tgz#f53d1f868b27fe74aca091a799f2af56237b15a2" - integrity sha512-p5RLE0QWyP0OcTOLmFcLdVgUcUEzmEfmdrnOxyNzomcYb0p3vUagA5zfa1HVK2azsQJFBv28GfvMnba9bGhObg== - dependencies: - "@aws-sdk/querystring-parser" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-base64@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz#36b430e5396251f761590f7c2f0c5c12193f353c" - integrity sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg== - dependencies: - "@aws-sdk/util-buffer-from" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/util-body-length-browser@3.188.0": - version "3.188.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz#e1d949318c10a621b38575a9ef01e39f9857ddb0" - integrity sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-body-length-node@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz#baabd1fa1206ff2bd4ce3785122d86eb3258dd20" - integrity sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-buffer-from@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz#285e86f6dc9030148a4147d65239e75cb254a1b0" - integrity sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw== - dependencies: - "@aws-sdk/is-array-buffer" "3.201.0" - tslib "^2.3.1" - -"@aws-sdk/util-config-provider@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz#c485fd83fbac051337e5f6be60ea3f9fa61c0139" - integrity sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-defaults-mode-browser@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.234.0.tgz#1151f0beabdb46c1aaca42a1ad0714b8e686acaa" - integrity sha512-IHMKXjTbOD8XMz5+2oCOsVP94BYb9YyjXdns0aAXr2NAo7k2+RCzXQ2DebJXppGda1F6opFutoKwyVSN0cmbMw== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - bowser "^2.11.0" - tslib "^2.3.1" - -"@aws-sdk/util-defaults-mode-node@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.234.0.tgz#0607f1dc7a4dc896dfcaf377522535ca9ffba7a9" - integrity sha512-UGjQ+OjBYYhxFVtUY+jtr0ZZgzZh6OHtYwRhFt8IHewJXFCfZTyfsbX20szBj5y1S4HRIUJ7cwBLIytTqMbI5w== - dependencies: - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/credential-provider-imds" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-endpoints@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.226.0.tgz#3728b2e30f6f757ae862a0b7cf3991e75f252c3f" - integrity sha512-iqOkac/zLmyPBUJd7SLN0PeZMkOmlGgD5PHmmekTClOkce2eUjK9SNX1PzL73aXPoPTyhg9QGLH8uEZEQ8YUzg== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-hex-encoding@3.201.0": - version "3.201.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz#21d7ec319240ee68c33d938e71cb79830bea315d" - integrity sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-locate-window@^3.0.0": - version "3.46.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.46.0.tgz#b1ad7eaae6b8f6dea61b3b1e7ddfcb51a0de9d14" - integrity sha512-g6V/7mozjlP2HhwHHgGgoOvcNRJasIQjh7ClkCMrMilfthD4WNtkWfcAZQD+BaPKkSgj8MnIOFvFzqULGeNQXA== - dependencies: - tslib "^2.3.0" - -"@aws-sdk/util-middleware@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.226.0.tgz#7069ae96e2e00f6bb82c722e073922fb2b051ca2" - integrity sha512-B96CQnwX4gRvQdaQkdUtqvDPkrptV5+va6FVeJOocU/DbSYMAScLxtR3peMS8cnlOT6nL1Eoa42OI9AfZz1VwQ== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-retry@3.229.0": - version "3.229.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.229.0.tgz#17aad47b067e81acf644d5c2c0f2325f2d8faf4f" - integrity sha512-0zKTqi0P1inD0LzIMuXRIYYQ/8c1lWMg/cfiqUcIAF1TpatlpZuN7umU0ierpBFud7S+zDgg0oemh+Nj8xliJw== - dependencies: - "@aws-sdk/service-error-classification" "3.229.0" - tslib "^2.3.1" - -"@aws-sdk/util-uri-escape@3.201.0": - version "3.201.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz#5e708d4cde001a4558ee616f889ceacfadd2ab03" - integrity sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-user-agent-browser@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.226.0.tgz#164bb2da8d6353133784e47f0a0ae463bc9ebb73" - integrity sha512-PhBIu2h6sPJPcv2I7ELfFizdl5pNiL4LfxrasMCYXQkJvVnoXztHA1x+CQbXIdtZOIlpjC+6BjDcE0uhnpvfcA== - dependencies: - "@aws-sdk/types" "3.226.0" - bowser "^2.11.0" - tslib "^2.3.1" - -"@aws-sdk/util-user-agent-node@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.226.0.tgz#7569460b9efc6bbd5295275c51357e480ff469c2" - integrity sha512-othPc5Dz/pkYkxH+nZPhc1Al0HndQT8zHD4e9h+EZ+8lkd8n+IsnLfTS/mSJWrfiC6UlNRVw55cItstmJyMe/A== - dependencies: - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-utf8-browser@3.188.0", "@aws-sdk/util-utf8-browser@^3.0.0": - version "3.188.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz#484762bd600401350e148277731d6744a4a92225" - integrity sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-utf8-node@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-node/-/util-utf8-node-3.208.0.tgz#eba17de0f92f87b98481c2e2d0ceaa05c7994d67" - integrity sha512-jKY87Acv0yWBdFxx6bveagy5FYjz+dtV8IPT7ay1E2WPWH1czoIdMAkc8tSInK31T6CRnHWkLZ1qYwCbgRfERQ== - dependencies: - "@aws-sdk/util-buffer-from" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/util-waiter@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.226.0.tgz#6715afd59748cbc610ddfbc5e21124b20a7e85ac" - integrity sha512-qYQMRxnu5k8qQihJXoIWMkBOj0+XkHHj/drLdbRnwL6ni6NcG8++cs9M3DSjIcxmxgF/7SLpDjn1H3sC7cYo4g== - dependencies: - "@aws-sdk/abort-controller" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/compat-data@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" - integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== - -"@babel/compat-data@^7.19.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.4.tgz#95c86de137bf0317f3a570e1b6e996b427299747" - integrity sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw== - -"@babel/core@7.17.8": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.8.tgz#3dac27c190ebc3a4381110d46c80e77efe172e1a" - integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.7" - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.8" - "@babel/parser" "^7.17.8" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c" - integrity sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.3" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-module-transforms" "^7.19.0" - "@babel/helpers" "^7.19.0" - "@babel/parser" "^7.19.3" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.3" - "@babel/types" "^7.19.3" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad" - integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.17.3", "@babel/generator@^7.17.7", "@babel/generator@^7.19.3", "@babel/generator@^7.19.4", "@babel/generator@^7.7.2": - version "7.19.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.5.tgz#da3f4b301c8086717eee9cab14da91b1fa5dcca7" - integrity sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg== - dependencies: - "@babel/types" "^7.19.4" - "@jridgewell/gen-mapping" "^0.3.2" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.17.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" - integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== - dependencies: - "@babel/compat-data" "^7.18.8" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz#a10a04588125675d7c7ae299af86fa1b2ee038ca" - integrity sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg== - dependencies: - "@babel/compat-data" "^7.19.3" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== - dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.17.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" - integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-module-transforms@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" - integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== - -"@babel/helper-plugin-utils@^7.18.6": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" - integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== - -"@babel/helper-simple-access@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" - integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helpers@^7.17.8": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" - integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== - dependencies: - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helpers@^7.19.0": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.4.tgz#42154945f87b8148df7203a25c31ba9a73be46c5" - integrity sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.4" - "@babel/types" "^7.19.4" - -"@babel/highlight@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" - integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539" - integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg== - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.17.8", "@babel/parser@^7.18.10", "@babel/parser@^7.18.6", "@babel/parser@^7.19.3", "@babel/parser@^7.19.4": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.0.tgz#b26133c888da4d79b0d3edcf42677bcadc783046" - integrity sha512-G9VgAhEaICnz8iiJeGJQyVl6J2nTjbW0xeisva0PK6XcKsga7BIaqm4ZF8Rg1Wbaqmy6znspNqhPaPkyukujzg== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/template@^7.16.7", "@babel/template@^7.3.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/template@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" - integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/traverse@7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.17.3", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.3", "@babel/traverse@^7.19.4", "@babel/traverse@^7.7.2": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.4.tgz#f117820e18b1e59448a6c1fa9d0ff08f7ac459a8" - integrity sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.4" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.19.4" - "@babel/types" "^7.19.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.3", "@babel/types@^7.19.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7" - integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw== - dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@eslint/eslintrc@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" - integrity sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.3.1.tgz#3e3f876e4e47616ea3b1464b9fbda981872e9583" - integrity sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - -"@jest/core@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.3.1.tgz#bff00f413ff0128f4debec1099ba7dcd649774a1" - integrity sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/reporters" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.2.0" - jest-config "^29.3.1" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-resolve-dependencies "^29.3.1" - jest-runner "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - jest-watcher "^29.3.1" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.3.1.tgz#eb039f726d5fcd14698acd072ac6576d41cfcaa6" - integrity sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag== - dependencies: - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-mock "^29.3.1" - -"@jest/expect-utils@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.3.1.tgz#531f737039e9b9e27c42449798acb5bba01935b6" - integrity sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g== - dependencies: - jest-get-type "^29.2.0" - -"@jest/expect@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.3.1.tgz#456385b62894349c1d196f2d183e3716d4c6a6cd" - integrity sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg== - dependencies: - expect "^29.3.1" - jest-snapshot "^29.3.1" - -"@jest/fake-timers@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.3.1.tgz#b140625095b60a44de820876d4c14da1aa963f67" - integrity sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A== - dependencies: - "@jest/types" "^29.3.1" - "@sinonjs/fake-timers" "^9.1.2" - "@types/node" "*" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -"@jest/globals@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.3.1.tgz#92be078228e82d629df40c3656d45328f134a0c6" - integrity sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/types" "^29.3.1" - jest-mock "^29.3.1" - -"@jest/reporters@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.3.1.tgz#9a6d78c109608e677c25ddb34f907b90e07b4310" - integrity sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - jest-worker "^29.3.1" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.0.0": - version "29.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" - integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== - dependencies: - "@sinclair/typebox" "^0.24.1" - -"@jest/source-map@^29.2.0": - version "29.2.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" - integrity sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.3.1.tgz#92cd5099aa94be947560a24610aa76606de78f50" - integrity sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz#fa24b3b050f7a59d48f7ef9e0b782ab65123090d" - integrity sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA== - dependencies: - "@jest/test-result" "^29.3.1" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - slash "^3.0.0" - -"@jest/transform@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.3.1.tgz#1e6bd3da4af50b5c82a539b7b1f3770568d6e36d" - integrity sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.1" - -"@jest/types@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" - integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== - dependencies: - "@jest/schemas" "^29.0.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@octokit/auth-app@4.0.7": - version "4.0.7" - resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-4.0.7.tgz#417c327e6a7ada1e6e9651db681146f8c12728e3" - integrity sha512-hjjVCoI/+1oLminVHJPPexguYb9FP4Q60hEHExgy1uAKMMJ5Zf8iJIeRJlIIqneTb4vt7NvUTEj4YDxBLZ1FLg== - dependencies: - "@octokit/auth-oauth-app" "^5.0.0" - "@octokit/auth-oauth-user" "^2.0.0" - "@octokit/request" "^6.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^8.0.0" - "@types/lru-cache" "^5.1.0" - deprecation "^2.3.1" - lru-cache "^6.0.0" - universal-github-app-jwt "^1.0.1" - universal-user-agent "^6.0.0" - -"@octokit/auth-oauth-app@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-5.0.1.tgz#294b5edd780d2fca296ade2aa21feba7690c2ac7" - integrity sha512-SGQKQGWe60kucMLCzbwc4MIohB78YawbYgGegosapDg2GxwuEVCujJccArzgn3wO+pB4aflUjFWPjkECVR2fEQ== - dependencies: - "@octokit/auth-oauth-device" "^4.0.0" - "@octokit/auth-oauth-user" "^2.0.0" - "@octokit/request" "^5.6.3" - "@octokit/types" "^6.0.3" - "@types/btoa-lite" "^1.0.0" - btoa-lite "^1.0.0" - universal-user-agent "^6.0.0" - -"@octokit/auth-oauth-device@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-4.0.0.tgz#f7527ec82d89813ee4a764d84ad1be69ee970cc3" - integrity sha512-2bXBuF5DOnYD19wDafZNrnrNvLg7xNvDNAf3ELHlO/7/7x3BBhKna4dCvpJ4pfI6OYMja08Tt0D4XJ4sxK+YBA== - dependencies: - "@octokit/oauth-methods" "^2.0.0" - "@octokit/request" "^6.0.0" - "@octokit/types" "^6.10.0" - universal-user-agent "^6.0.0" - -"@octokit/auth-oauth-user@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-2.0.2.tgz#03c2b7455fd2d48a72715a84d895c95effad7d77" - integrity sha512-fr9+jPjkWG7cvpyUVnpJJH5F+wNCswRy9rTTwHUAXdy6z/kZj9uenPmUYdE6mja3wSTJUAt2yRqkfaaltzQlFA== - dependencies: - "@octokit/auth-oauth-device" "^4.0.0" - "@octokit/oauth-methods" "^2.0.0" - "@octokit/request" "^6.0.0" - "@octokit/types" "^6.12.2" - btoa-lite "^1.0.0" - universal-user-agent "^6.0.0" - -"@octokit/auth-token@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.0.tgz#6f22c5fc56445c496628488ba6810131558fa4a9" - integrity sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ== - dependencies: - "@octokit/types" "^6.0.3" - -"@octokit/core@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.1.0.tgz#b6b03a478f1716de92b3f4ec4fd64d05ba5a9251" - integrity sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ== - dependencies: - "@octokit/auth-token" "^3.0.0" - "@octokit/graphql" "^5.0.0" - "@octokit/request" "^6.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^8.0.0" - before-after-hook "^2.2.0" - universal-user-agent "^6.0.0" - -"@octokit/endpoint@^6.0.1": - version "6.0.12" - resolved "https://registry.yarnpkg.com/@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/endpoint@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.0.tgz#be758a1236d68d6bbb505e686dd50881c327a519" - integrity sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ== - dependencies: - "@octokit/types" "^6.0.3" - is-plain-object "^5.0.0" - universal-user-agent "^6.0.0" - -"@octokit/graphql@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.0.tgz#2cc6eb3bf8e0278656df1a7d0ca0d7591599e3b3" - integrity sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ== - dependencies: - "@octokit/request" "^6.0.0" - "@octokit/types" "^6.0.3" - universal-user-agent "^6.0.0" - -"@octokit/oauth-authorization-url@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-5.0.0.tgz#029626ce87f3b31addb98cd0d2355c2381a1c5a1" - integrity sha512-y1WhN+ERDZTh0qZ4SR+zotgsQUE1ysKnvBt1hvDRB2WRzYtVKQjn97HEPzoehh66Fj9LwNdlZh+p6TJatT0zzg== - -"@octokit/oauth-methods@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-2.0.2.tgz#91285b972b80569f2cdc07986923c8c240bcac24" - integrity sha512-AHF5bWGhgnZwH8fn4sgPLyVouRqMOafMSM2zX1de+aLZGZaS9rANK9RXH2d5fGvXjGEw3XR+ruNPZ0gwhM4QwA== - dependencies: - "@octokit/oauth-authorization-url" "^5.0.0" - "@octokit/request" "^6.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^6.12.2" - btoa-lite "^1.0.0" - -"@octokit/openapi-types@^12.11.0": - version "12.11.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-12.11.0.tgz#da5638d64f2b919bca89ce6602d059f1b52d3ef0" - integrity sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ== - -"@octokit/openapi-types@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a" - integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw== - -"@octokit/plugin-paginate-rest@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz#93d7e74f1f69d68ba554fa6b888c2a9cf1f99a83" - integrity sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw== - dependencies: - "@octokit/types" "^8.0.0" - -"@octokit/plugin-request-log@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" - integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== - -"@octokit/plugin-rest-endpoint-methods@^6.7.0": - version "6.7.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz#2f6f17f25b6babbc8b41d2bb0a95a8839672ce7c" - integrity sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw== - dependencies: - "@octokit/types" "^8.0.0" - deprecation "^2.3.1" - -"@octokit/request-error@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@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-error@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.0.tgz#f527d178f115a3b62d76ce4804dd5bdbc0270a81" - integrity sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w== - dependencies: - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^5.6.3": - version "5.6.3" - resolved "https://registry.yarnpkg.com/@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/request@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.1.0.tgz#80bdac78dff583a8fa0978baeda139a71d98d10c" - integrity sha512-36V+sP4bJli31TRq8sea3d/Q1XGgZ9cnqpsegkLCnvpu+hoYephSkxGlWg4KB6dyUM1IWPXVrLFOKYzObQ+MZg== - dependencies: - "@octokit/endpoint" "^7.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^6.16.1" - is-plain-object "^5.0.0" - node-fetch "^2.6.7" - universal-user-agent "^6.0.0" - -"@octokit/rest@^19.0.5": - version "19.0.5" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.5.tgz#4dbde8ae69b27dca04b5f1d8119d282575818f6c" - integrity sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow== - dependencies: - "@octokit/core" "^4.1.0" - "@octokit/plugin-paginate-rest" "^5.0.0" - "@octokit/plugin-request-log" "^1.0.4" - "@octokit/plugin-rest-endpoint-methods" "^6.7.0" - -"@octokit/types@^6.0.3", "@octokit/types@^6.10.0", "@octokit/types@^6.12.2", "@octokit/types@^6.16.1": - version "6.41.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.41.0.tgz#e58ef78d78596d2fb7df9c6259802464b5f84a04" - integrity sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg== - dependencies: - "@octokit/openapi-types" "^12.11.0" - -"@octokit/types@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.0.0.tgz#93f0b865786c4153f0f6924da067fe0bb7426a9f" - integrity sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg== - dependencies: - "@octokit/openapi-types" "^14.0.0" - -"@sinclair/typebox@^0.24.1": - version "0.24.20" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.20.tgz#11a657875de6008622d53f56e063a6347c51a6dd" - integrity sha512-kVaO5aEFZb33nPMTZBxiPEkY+slxiPtqC7QX8f9B3eGOMBvEfuMfxp9DSTTCsRJPumPKjrge4yagyssO4q6qzQ== - -"@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^9.1.2": - version "9.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" - integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== - dependencies: - "@sinonjs/commons" "^1.7.0" - -"@trivago/prettier-plugin-sort-imports@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.0.0.tgz#e0936d87fb8d65865c857e6a6dba644103db1b30" - integrity sha512-Tyuk5ZY4a0e2MNFLdluQO9F6d1awFQYXVVujEPFfvKPPXz8DADNHzz73NMhwCSXGSuGGZcA/rKOyZBrxVNMxaA== - dependencies: - "@babel/core" "7.17.8" - "@babel/generator" "7.17.7" - "@babel/parser" "7.18.9" - "@babel/traverse" "7.17.3" - "@babel/types" "7.17.0" - javascript-natural-sort "0.7.1" - lodash "4.17.21" - -"@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== - -"@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== - -"@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== - -"@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== - -"@types/aws-lambda@^8.10.109": - version "8.10.109" - resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.109.tgz#2f434cbfafe083529e365fe9c114787827a169a8" - integrity sha512-/ME92FneNyXQzrAfcnQQlW1XkCZGPDlpi2ao1MJwecN+6SbeonKeggU8eybv1DfKli90FAVT1MlIZVXfwVuCyg== - -"@types/babel__core@^7.1.14": - version "7.1.18" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8" - integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.4" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" - integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" - integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== - dependencies: - "@babel/types" "^7.3.0" - -"@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/btoa-lite@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/btoa-lite/-/btoa-lite-1.0.0.tgz#e190a5a548e0b348adb0df9ac7fa5f1151c7cca4" - integrity sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg== - -"@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== - dependencies: - "@types/node" "*" - -"@types/express-serve-static-core@^4.17.31": - version "4.17.31" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" - integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express@^4.17.15": - version "4.17.15" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.15.tgz#9290e983ec8b054b65a5abccb610411953d417ff" - integrity sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.31" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/graceful-fs@^4.1.3": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^29.2.4": - version "29.2.4" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.2.4.tgz#9c155c4b81c9570dbd183eb8604aa0ae80ba5a5b" - integrity sha512-PipFB04k2qTRPePduVLTRiPzQfvMeLwUN3Z21hsAKaB/W9IIzgB2pizCL466ftJlcyZqnHoC9ZHpxLGl3fS86A== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - -"@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/jsonwebtoken@^8.3.3": - version "8.5.6" - resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.6.tgz#1913e5a61e70a192c5a444623da4901a7b1a9d42" - integrity sha512-+P3O/xC7nzVizIi5VbF34YtqSonFsdnbXBnWUCYRiKOi1f9gA4sEFvXkrGr/QVV23IbMYvcoerI7nnhDUiWXRQ== - dependencies: - "@types/node" "*" - -"@types/lru-cache@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" - integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== - -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - -"@types/node@*": - version "18.11.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.12.tgz#89e7f8aa8c88abf432f9bd594888144d7dba10aa" - integrity sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg== - -"@types/node@^18.11.18": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== - -"@types/prettier@^2.1.5": - version "2.4.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" - integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== - -"@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== - -"@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== - -"@types/semver@^7.3.12": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== - -"@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== - -"@types/strip-bom@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" - integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= - -"@types/strip-json-comments@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" - integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== - -"@types/yargs-parser@*": - version "20.2.1" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" - integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== - -"@types/yargs@^17.0.8": - version "17.0.10" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a" - integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz#50cc5085578a7fa22cd46a0806c2e5eae858af02" - integrity sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/type-utils" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.1.tgz#c4bf16f8c3c7608ce4bf8ff804b677fc899f173f" - integrity sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz#0d302b3c2f20ab24e4787bf3f5a0d8c449b823bd" - integrity sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - -"@typescript-eslint/type-utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz#aee13314f840ab336c1adb49a300856fd16d04ce" - integrity sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w== - dependencies: - "@typescript-eslint/typescript-estree" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.1.tgz#459f07428aec5a8c4113706293c2ae876741ac8e" - integrity sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A== - -"@typescript-eslint/typescript-estree@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz#b9d8441308aca53df7f69b2c67a887b82c9ed418" - integrity sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.1.tgz#595f25ac06e9ee28c339fd43c709402820b13d7b" - integrity sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw== - dependencies: - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz#d35c2da544dbb685db9c5b5b85adac0a1d74d1f2" - integrity sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig== - dependencies: - "@typescript-eslint/types" "5.47.1" - eslint-visitor-keys "^3.3.0" - -"@vercel/ncc@^0.36.0": - version "0.36.0" - resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.36.0.tgz#1f262b86fc4f0770bbc0fc1d331d5aaa1bd47334" - integrity sha512-/ZTUJ/ZkRt694k7KJNimgmHjtQcRuVwsST2Z6XfYveQIuBbHR+EqkTc1jfgPkQmMyk/vtpxo3nVxe8CNuau86A== - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - -acorn@^8.8.0: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -aws-sdk@^2.1283.0: - version "2.1283.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1283.0.tgz#87dafacd3e4c9dd89f5de0bce43cafb50fd5c9e4" - integrity sha512-YlxTF0T9X8AcNrOzFPVOPnX1jNtHZjYHRUCfpsVwqdajHDGGruVsVppgBYXEiCRuTQNUhcJTUx0J0uKBhKQZIA== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.4.19" - -babel-jest@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.3.1.tgz#05c83e0d128cd48c453eea851482a38782249f44" - integrity sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA== - dependencies: - "@jest/transform" "^29.3.1" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.2.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz#23ee99c37390a98cfddf3ef4a78674180d823094" - integrity sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" - integrity sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA== - dependencies: - babel-plugin-jest-hoist "^29.2.0" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -bowser@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" - integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.20.2: - version "4.21.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf" - integrity sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA== - dependencies: - caniuse-lite "^1.0.30001366" - electron-to-chromium "^1.4.188" - node-releases "^2.0.6" - update-browserslist-db "^1.0.4" - -browserslist@^4.21.3: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== - dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" - -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -btoa-lite@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" - integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= - -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001366: - version "1.0.30001368" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz#c5c06381c6051cd863c45021475434e81936f713" - integrity sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ== - -caniuse-lite@^1.0.30001400: - version "1.0.30001420" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001420.tgz#f62f35f051e0b6d25532cf376776d41e45b47ef6" - integrity sha512-OnyeJ9ascFA9roEj72ok2Ikp7PHJTKubtEJIQ/VK3fdsS50q4KWy+Z5X0A1/GswEItKX0ctAp8n4SYDE7wTu6A== - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -ci-info@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" - integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== - -cjs-module-lexer@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" - integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cron-parser@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.7.0.tgz#184eac151f810e7bf2b32ad37b4dd4a711797cdc" - integrity sha512-BdAELR+MCT2ZWsIBhZKDuUqIUCBjHHulPJnm53OfdRLA4EWBjva3R+KM5NeidJuGsNXdEcZkjC7SCnkW5rAFSA== - dependencies: - luxon "^3.1.0" - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - -debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -deprecation@^2.0.0, deprecation@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/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" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -diff-sequences@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" - integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dynamic-dedupe@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" - integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= - dependencies: - xtend "^4.0.0" - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - -electron-to-chromium@^1.4.188: - version "1.4.196" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.196.tgz#e18cdc5c1c2c2ebf78da237d0c374cc3b244d4cb" - integrity sha512-uxMa/Dt7PQsLBVXwH+t6JvpHJnrsYBaxWKi/J6HE+/nBtoHENhwBoNkgkm226/Kfxeg0z1eMQLBRPPKcDH8xWA== - -electron-to-chromium@^1.4.251: - version "1.4.283" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.283.tgz#d4f263f5df402fd799c0a06255d580dcf8aa9a8e" - integrity sha512-g6RQ9zCOV+U5QVHW9OpFR7rdk/V7xfopNXnyAamdpFgCHgZ1sjI8VuR1+zG2YG/TZk+tQ8mpNkug4P8FU0fuOA== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0: - version "1.20.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-plugin-prettier@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^8.30.0: - version "8.30.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" - integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== - dependencies: - "@eslint/eslintrc" "^1.4.0" - "@humanwhocodes/config-array" "^0.11.8" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expect@^29.0.0, expect@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.3.1.tgz#92877aad3f7deefc2e3f6430dd195b92295554a6" - integrity sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA== - dependencies: - "@jest/expect-utils" "^29.3.1" - jest-get-type "^29.2.0" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.2.9: - version "3.2.10" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.10.tgz#2734f83baa7f43b7fd41e13bc34438f4ffe284ee" - integrity sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fast-xml-parser@4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz#42332a9aca544520631c8919e6ea871c0185a985" - integrity sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA== - dependencies: - strnum "^1.0.5" - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== - dependencies: - bser "2.1.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" - integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob@^7.1.3, glob@^7.1.4: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.19.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" - integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-core-module@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" - integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" - for-each "^0.3.3" - has-tostringtag "^1.0.0" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" - integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" - integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -javascript-natural-sort@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" - integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= - -jest-changed-files@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289" - integrity sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA== - dependencies: - execa "^5.0.0" - p-limit "^3.1.0" - -jest-circus@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.3.1.tgz#177d07c5c0beae8ef2937a67de68f1e17bbf1b4a" - integrity sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - p-limit "^3.1.0" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.3.1.tgz#e89dff427db3b1df50cea9a393ebd8640790416d" - integrity sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ== - dependencies: - "@jest/core" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-config@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.3.1.tgz#0bc3dcb0959ff8662957f1259947aedaefb7f3c6" - integrity sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.3.1" - "@jest/types" "^29.3.1" - babel-jest "^29.3.1" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.3.1" - jest-environment-node "^29.3.1" - jest-get-type "^29.2.0" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-runner "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" - integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-docblock@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" - integrity sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.3.1.tgz#bc375c8734f1bb96625d83d1ca03ef508379e132" - integrity sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA== - dependencies: - "@jest/types" "^29.3.1" - chalk "^4.0.0" - jest-get-type "^29.2.0" - jest-util "^29.3.1" - pretty-format "^29.3.1" - -jest-environment-node@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.3.1.tgz#5023b32472b3fba91db5c799a0d5624ad4803e74" - integrity sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -jest-get-type@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" - integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== - -jest-haste-map@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.3.1.tgz#af83b4347f1dae5ee8c2fb57368dc0bb3e5af843" - integrity sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A== - dependencies: - "@jest/types" "^29.3.1" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - jest-worker "^29.3.1" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz#95336d020170671db0ee166b75cd8ef647265518" - integrity sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA== - dependencies: - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-matcher-utils@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572" - integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ== - dependencies: - chalk "^4.0.0" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-message-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" - integrity sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.3.1" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock-extended@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jest-mock-extended/-/jest-mock-extended-3.0.1.tgz#5f109d5e1da62851ffc9126a01e83cd6470b810b" - integrity sha512-RF4Ow8pXvbRuEcCTj56oYHmig5311BSFvbEGxPNYL51wGKGu93MvVQgx0UpFmjqyBXIcElkZo2Rke88kR1iSKQ== - dependencies: - ts-essentials "^7.0.3" - -jest-mock@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.3.1.tgz#60287d92e5010979d01f218c6b215b688e0f313e" - integrity sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-util "^29.3.1" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" - integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== - -jest-resolve-dependencies@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz#a6a329708a128e68d67c49f38678a4a4a914c3bf" - integrity sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA== - dependencies: - jest-regex-util "^29.2.0" - jest-snapshot "^29.3.1" - -jest-resolve@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.3.1.tgz#9a4b6b65387a3141e4a40815535c7f196f1a68a7" - integrity sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-pnp-resolver "^1.2.2" - jest-util "^29.3.1" - jest-validate "^29.3.1" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" - -jest-runner@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.3.1.tgz#a92a879a47dd096fea46bb1517b0a99418ee9e2d" - integrity sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA== - dependencies: - "@jest/console" "^29.3.1" - "@jest/environment" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.2.0" - jest-environment-node "^29.3.1" - jest-haste-map "^29.3.1" - jest-leak-detector "^29.3.1" - jest-message-util "^29.3.1" - jest-resolve "^29.3.1" - jest-runtime "^29.3.1" - jest-util "^29.3.1" - jest-watcher "^29.3.1" - jest-worker "^29.3.1" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.3.1.tgz#21efccb1a66911d6d8591276a6182f520b86737a" - integrity sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/globals" "^29.3.1" - "@jest/source-map" "^29.2.0" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.3.1.tgz#17bcef71a453adc059a18a32ccbd594b8cc4e45e" - integrity sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.3.1" - graceful-fs "^4.2.9" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - jest-haste-map "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - natural-compare "^1.4.0" - pretty-format "^29.3.1" - semver "^7.3.5" - -jest-util@^29.0.0, jest-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" - integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.3.1.tgz#d56fefaa2e7d1fde3ecdc973c7f7f8f25eea704a" - integrity sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g== - dependencies: - "@jest/types" "^29.3.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.2.0" - leven "^3.1.0" - pretty-format "^29.3.1" - -jest-watcher@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.3.1.tgz#3341547e14fe3c0f79f9c3a4c62dbc3fc977fd4a" - integrity sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg== - dependencies: - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.3.1" - string-length "^4.0.1" - -jest-worker@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" - integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== - dependencies: - "@types/node" "*" - jest-util "^29.3.1" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.3: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.3.1.tgz#c130c0d551ae6b5459b8963747fed392ddbde122" - integrity sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA== - dependencies: - "@jest/core" "^29.3.1" - "@jest/types" "^29.3.1" - import-local "^3.0.2" - jest-cli "^29.3.1" - -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - -js-sdsl@^4.1.4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" - integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -jsonwebtoken@^8.5.1: - version "8.5.1" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" - integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^5.6.0" - -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= - -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= - -lodash@4.17.21, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -luxon@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.1.1.tgz#b492c645b2474fb86f3bd3283213846b99c32c1e" - integrity sha512-Ah6DloGmvseB/pX1cAmjbFvyU/pKuwQMQqz7d0yvuDlVYLTs2WeDHQMpC8tGjm1da+BriHROW/OEIT/KfYg6xw== - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -make-error@1.x, make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.5, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -moment-timezone@^0.5.40: - version "0.5.40" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.40.tgz#c148f5149fd91dd3e29bf481abc8830ecba16b89" - integrity sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg== - dependencies: - moment ">= 2.9.0" - -"moment@>= 2.9.0": - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -nock@^13.2.9: - version "13.2.9" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.2.9.tgz#4faf6c28175d36044da4cfa68e33e5a15086ad4c" - integrity sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.21" - propagate "^2.0.0" - -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - 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" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-inspect@^1.12.0, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -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= - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pirates@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" - integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" - integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== - -pretty-format@^29.0.0, pretty-format@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" - integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== - dependencies: - "@jest/schemas" "^29.0.0" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -propagate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" - integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== - -resolve@^1.0.0, resolve@^1.20.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" - integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== - dependencies: - is-core-module "^2.8.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= - -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@7.x, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.7: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - -signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@^0.5.12, source-map-support@^0.5.21: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== - dependencies: - escape-string-regexp "^2.0.0" - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-essentials@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" - integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== - -ts-jest@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" - integrity sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.1" - lodash.memoize "4.x" - make-error "1.x" - semver "7.x" - yargs-parser "^21.0.1" - -ts-node-dev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" - integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== - dependencies: - chokidar "^3.5.1" - dynamic-dedupe "^0.3.0" - minimist "^1.2.6" - mkdirp "^1.0.4" - resolve "^1.0.0" - rimraf "^2.6.1" - source-map-support "^0.5.12" - tree-kill "^1.2.2" - ts-node "^10.4.0" - tsconfig "^7.0.0" - -ts-node@^10.4.0, ts-node@^10.9.1: - version "10.9.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" - integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" - integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== - dependencies: - "@types/strip-bom" "^3.0.0" - "@types/strip-json-comments" "0.0.30" - strip-bom "^3.0.0" - strip-json-comments "^2.0.0" - -tslib@^1.11.1, tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.3.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -tslog@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.3.4.tgz#083197a908c97b3b714a0576b9dac293f223f368" - integrity sha512-N0HHuHE0e/o75ALfkioFObknHR5dVchUad4F0XyFf3gXJYB++DewEzwGI/uIOM216E5a43ovnRNEeQIq9qgm4Q== - dependencies: - source-map-support "^0.5.21" - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -typescript@^4.9.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -universal-github-app-jwt@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.0.tgz#0abaa876101cdf1d3e4c546be2768841c0c1b514" - integrity sha512-3b+ocAjjz4JTyqaOT+NNBd5BtTuvJTxWElIoeHSVelUV9J3Jp7avmQTdLKCaoqi/5Ox2o/q+VK19TJ233rVXVQ== - dependencies: - "@types/jsonwebtoken" "^8.3.3" - jsonwebtoken "^8.5.1" - -universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== - -update-browserslist-db@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" - integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -update-browserslist-db@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -util@^0.12.4: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -v8-to-istanbul@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" - integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" - integrity sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" - for-each "^0.3.3" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.9" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.0.0, yargs-parser@^21.0.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c" - integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/modules/runners/logging.tf b/modules/runners/logging.tf index 65f5b517e8..1b61f16f7b 100644 --- a/modules/runners/logging.tf +++ b/modules/runners/logging.tf @@ -42,7 +42,7 @@ locals { resource "aws_ssm_parameter" "cloudwatch_agent_config_runner" { count = var.enable_cloudwatch_agent ? 1 : 0 - name = "${var.prefix}-cloudwatch_agent_config_runner" + name = "${var.ssm_paths.root}/${var.ssm_paths.config}/cloudwatch_agent_config_runner" type = "String" value = var.cloudwatch_config != null ? var.cloudwatch_config : templatefile("${path.module}/templates/cloudwatch_config.json", { logfiles = jsonencode(local.logfiles) diff --git a/modules/runners/main.tf b/modules/runners/main.tf index d2330eaf63..625ebd4ed0 100644 --- a/modules/runners/main.tf +++ b/modules/runners/main.tf @@ -3,6 +3,9 @@ locals { { "Name" = format("%s-action-runner", var.prefix) }, + { + "ghr:ssm_config_path" = "${var.ssm_paths.root}/${var.ssm_paths.config}" + }, var.tags, ) @@ -10,14 +13,13 @@ locals { name_runner = var.overrides["name_runner"] == "" ? local.tags["Name"] : var.overrides["name_runner"] role_path = var.role_path == null ? "/${var.prefix}/" : var.role_path instance_profile_path = var.instance_profile_path == null ? "/${var.prefix}/" : var.instance_profile_path - lambda_zip = var.lambda_zip == null ? "${path.module}/lambdas/runners/runners.zip" : var.lambda_zip + lambda_zip = var.lambda_zip == null ? "${path.module}/../../lambdas/functions/control-plane/runners.zip" : var.lambda_zip userdata_template = var.userdata_template == null ? local.default_userdata_template[var.runner_os] : var.userdata_template kms_key_arn = var.kms_key_arn != null ? var.kms_key_arn : "" s3_location_runner_distribution = var.enable_runner_binaries_syncer ? "s3://${var.s3_runner_binaries.id}/${var.s3_runner_binaries.key}" : "" - default_ami = { - "windows" = { name = ["Windows_Server-2022-English-Core-ContainersLatest-*"] } - "linux" = var.runner_architecture == "arm64" ? { name = ["amzn2-ami-kernel-5.*-hvm-*-arm64-gp2"] } : { name = ["amzn2-ami-kernel-5.*-hvm-*-x86_64-gp2"] } + "windows" = { name = ["Windows_Server-2022-English-Full-ECS_Optimized-*"] } + "linux" = var.runner_architecture == "arm64" ? { name = ["al2023-ami-2023.*-kernel-6.*-arm64"] } : { name = ["al2023-ami-2023.*-kernel-6.*-x86_64"] } } default_userdata_template = { @@ -35,9 +37,35 @@ locals { "linux" = "${path.module}/templates/start-runner.sh" } - ami_filter = coalesce(var.ami_filter, local.default_ami[var.runner_os]) + ami_kms_key_arn = var.ami_kms_key_arn != null ? var.ami_kms_key_arn : "" + ami_filter = merge(local.default_ami[var.runner_os], var.ami_filter) enable_job_queued_check = var.enable_job_queued_check == null ? !var.enable_ephemeral_runners : var.enable_job_queued_check + + arn_ssm_parameters_path_config = "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${var.ssm_paths.root}/${var.ssm_paths.config}" + + token_path = "${var.ssm_paths.root}/${var.ssm_paths.tokens}" + + user_data = var.enable_userdata ? (var.userdata_content == null ? templatefile(local.userdata_template, { + enable_debug_logging = var.enable_user_data_debug_logging + s3_location_runner_distribution = local.s3_location_runner_distribution + pre_install = var.userdata_pre_install + install_runner = templatefile(local.userdata_install_runner[var.runner_os], { + S3_LOCATION_RUNNER_DISTRIBUTION = local.s3_location_runner_distribution + RUNNER_ARCHITECTURE = var.runner_architecture + }) + post_install = var.userdata_post_install + start_runner = templatefile(local.userdata_start_runner[var.runner_os], { + metadata_tags = var.metadata_options != null ? var.metadata_options.instance_metadata_tags : "enabled" + }) + ghes_url = var.ghes_url + ghes_ssl_verify = var.ghes_ssl_verify + + ## retain these for backwards compatibility + environment = var.prefix + enable_cloudwatch_agent = var.enable_cloudwatch_agent + ssm_key_cloudwatch_agent_config = var.enable_cloudwatch_agent ? aws_ssm_parameter.cloudwatch_agent_config_runner[0].name : "" + }) : var.userdata_content) : "" } data "aws_ami" "runner" { @@ -94,6 +122,13 @@ resource "aws_launch_template" "runner" { } } + dynamic "credit_specification" { + for_each = var.credit_specification != null ? [var.credit_specification] : [] + content { + cpu_credits = credit_specification.value + } + } + monitoring { enabled = var.enable_runner_detailed_monitoring } @@ -105,11 +140,12 @@ resource "aws_launch_template" "runner" { instance_initiated_shutdown_behavior = "terminate" image_id = data.aws_ami.runner.id key_name = var.key_name + ebs_optimized = var.ebs_optimized - vpc_security_group_ids = compact(concat( + vpc_security_group_ids = !var.associate_public_ipv4_address ? compact(concat( var.enable_managed_runner_security_group ? [aws_security_group.runner_sg[0].id] : [], var.runner_additional_security_group_ids, - )) + )) : [] tag_specifications { resource_type = "instance" @@ -118,6 +154,9 @@ resource "aws_launch_template" "runner" { { "Name" = format("%s", local.name_runner) }, + { + "ghr:runner_name_prefix" = var.runner_name_prefix + }, var.runner_ec2_tags ) } @@ -129,31 +168,30 @@ resource "aws_launch_template" "runner" { { "Name" = format("%s", local.name_runner) }, + { + "ghr:runner_name_prefix" = var.runner_name_prefix + }, + var.runner_ec2_tags ) } - user_data = var.enabled_userdata ? base64encode(templatefile(local.userdata_template, { - enable_debug_logging = var.enable_user_data_debug_logging - s3_location_runner_distribution = local.s3_location_runner_distribution - pre_install = var.userdata_pre_install - install_runner = templatefile(local.userdata_install_runner[var.runner_os], { - S3_LOCATION_RUNNER_DISTRIBUTION = local.s3_location_runner_distribution - RUNNER_ARCHITECTURE = var.runner_architecture - }) - post_install = var.userdata_post_install - start_runner = templatefile(local.userdata_start_runner[var.runner_os], {}) - ghes_url = var.ghes_url - ghes_ssl_verify = var.ghes_ssl_verify - - ## retain these for backwards compatibility - environment = var.prefix - enable_cloudwatch_agent = var.enable_cloudwatch_agent - ssm_key_cloudwatch_agent_config = var.enable_cloudwatch_agent ? aws_ssm_parameter.cloudwatch_agent_config_runner[0].name : "" - })) : "" + user_data = var.runner_os == "windows" ? base64encode(local.user_data) : base64gzip(local.user_data) tags = local.tags update_default_version = true + + dynamic "network_interfaces" { + for_each = var.associate_public_ipv4_address ? [var.associate_public_ipv4_address] : [] + iterator = associate_public_ipv4_address + content { + associate_public_ip_address = associate_public_ipv4_address.value + security_groups = compact(concat( + var.enable_managed_runner_security_group ? [aws_security_group.runner_sg[0].id] : [], + var.runner_additional_security_group_ids, + )) + } + } } resource "aws_security_group" "runner_sg" { @@ -163,6 +201,8 @@ resource "aws_security_group" "runner_sg" { vpc_id = var.vpc_id + ingress = [] + dynamic "egress" { for_each = var.egress_rules iterator = each diff --git a/modules/runners/outputs.tf b/modules/runners/outputs.tf index 21354ce02a..8f366dce90 100644 --- a/modules/runners/outputs.tf +++ b/modules/runners/outputs.tf @@ -10,6 +10,10 @@ output "lambda_scale_up" { value = aws_lambda_function.scale_up } +output "lambda_scale_up_log_group" { + value = aws_cloudwatch_log_group.scale_up +} + output "role_scale_up" { value = aws_iam_role.scale_up } @@ -18,10 +22,32 @@ output "lambda_scale_down" { value = aws_lambda_function.scale_down } +output "lambda_scale_down_log_group" { + value = aws_cloudwatch_log_group.scale_down +} + output "role_scale_down" { value = aws_iam_role.scale_down } +output "lambda_pool" { + value = try(module.pool[0].lambda, null) +} + +output "lambda_pool_log_group" { + value = try(module.pool[0].lambda_log_group, null) +} + output "role_pool" { - value = length(var.pool_config) == 0 ? null : module.pool[0].role_pool + value = try(module.pool[0].role_pool, null) +} + +output "runners_log_groups" { + description = "List of log groups from different log files of runner machine." + value = try(aws_cloudwatch_log_group.gh_runners, []) +} + +output "logfiles" { + value = local.logfiles + description = "List of logfiles to send to CloudWatch. Object description: `log_group_name`: Name of the log group, `file_path`: path to the log file, `log_stream_name`: name of the log stream." } diff --git a/modules/runners/policies-lambda-common.tf b/modules/runners/policies-lambda-common.tf index 1faeb55cce..feb0d39fd9 100644 --- a/modules/runners/policies-lambda-common.tf +++ b/modules/runners/policies-lambda-common.tf @@ -8,3 +8,44 @@ data "aws_iam_policy_document" "lambda_assume_role_policy" { } } } + +resource "aws_iam_policy" "ami_id_ssm_parameter_read" { + count = var.ami_id_ssm_parameter_name != null ? 1 : 0 + name = "${var.prefix}-ami-id-ssm-parameter-read" + path = local.role_path + description = "Allows for reading ${var.prefix} GitHub runner AMI ID from an SSM parameter" + tags = local.tags + policy = <<-JSON + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ssm:GetParameter" + ], + "Resource": [ + "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter/${trimprefix(var.ami_id_ssm_parameter_name, "/")}" + ] + } + ] + } + JSON +} + +data "aws_iam_policy_document" "lambda_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + statement { + actions = [ + "xray:BatchGetTraces", + "xray:GetTraceSummaries", + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ] + effect = "Allow" + resources = [ + "*" + ] + sid = "AllowXRay" + } +} diff --git a/modules/runners/policies-runner.tf b/modules/runners/policies-runner.tf index 49f6b903de..d1b9190930 100644 --- a/modules/runners/policies-runner.tf +++ b/modules/runners/policies-runner.tf @@ -12,6 +12,7 @@ resource "aws_iam_instance_profile" "runner" { name = "${var.prefix}-runner-profile" role = aws_iam_role.runner.name path = local.instance_profile_path + tags = local.tags } resource "aws_iam_role_policy" "runner_session_manager_aws_managed" { @@ -26,8 +27,8 @@ resource "aws_iam_role_policy" "ssm_parameters" { role = aws_iam_role.runner.name policy = templatefile("${path.module}/policies/instance-ssm-parameters-policy.json", { - arn_ssm_parameters_prefix = "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter/${var.prefix}-*" - arn_ssm_parameters_path = "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter/${var.prefix}/*" + arn_ssm_parameters_path_tokens = "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${var.ssm_paths.root}/${var.ssm_paths.tokens}" + arn_ssm_parameters_path_config = local.arn_ssm_parameters_path_config } ) } @@ -44,6 +45,12 @@ resource "aws_iam_role_policy" "dist_bucket" { ) } +resource "aws_iam_role_policy_attachment" "xray_tracing" { + count = var.tracing_config.mode != null ? 1 : 0 + role = aws_iam_role.runner.name + policy_arn = "arn:${var.aws_partition}:iam::aws:policy/AWSXRayDaemonWriteAccess" +} + resource "aws_iam_role_policy" "describe_tags" { name = "runner-describe-tags" role = aws_iam_role.runner.name @@ -63,4 +70,4 @@ resource "aws_iam_role_policy" "ec2" { policy = templatefile("${path.module}/policies/instance-ec2.json", {}) } -// see also logging.tf for logging and metrics policies +# see also logging.tf for logging and metrics policies diff --git a/modules/runners/policies/instance-ssm-parameters-policy.json b/modules/runners/policies/instance-ssm-parameters-policy.json index 5a7aa9e356..fcd82304e1 100644 --- a/modules/runners/policies/instance-ssm-parameters-policy.json +++ b/modules/runners/policies/instance-ssm-parameters-policy.json @@ -4,9 +4,16 @@ { "Effect": "Allow", "Action": [ - "ssm:DeleteParameter" + "ssm:DeleteParameter", + "ssm:GetParameters", + "ssm:GetParameter" ], - "Resource": "${arn_ssm_parameters_prefix}" + "Resource": "${arn_ssm_parameters_path_tokens}/*", + "Condition": { + "StringLike": { + "ec2:SourceInstanceARN": "*/$${aws:ResourceTag/InstanceId}" + } + } }, { "Effect": "Allow", @@ -16,9 +23,9 @@ "ssm:GetParametersByPath" ], "Resource": [ - "${arn_ssm_parameters_prefix}", - "${arn_ssm_parameters_path}" - ] + "${arn_ssm_parameters_path_config}", + "${arn_ssm_parameters_path_config}/*" + ] } ] } diff --git a/modules/runners/policies/lambda-scale-up.json b/modules/runners/policies/lambda-scale-up.json index e194535bc9..1c5e942b2f 100644 --- a/modules/runners/policies/lambda-scale-up.json +++ b/modules/runners/policies/lambda-scale-up.json @@ -22,7 +22,8 @@ { "Effect": "Allow", "Action": [ - "ssm:PutParameter" + "ssm:PutParameter", + "ssm:AddTagsToResource" ], "Resource": "*" }, @@ -33,7 +34,8 @@ ], "Resource": [ "${github_app_key_base64_arn}", - "${github_app_id_arn}" + "${github_app_id_arn}", + "${ssm_config_path}/*" ] }, { @@ -52,6 +54,29 @@ "kms:Decrypt" ], "Resource": "${kms_key_arn}" +%{ endif ~} +%{ if ami_kms_key_arn != "" ~} + }, + { + "Effect": "Allow", + "Action": [ + "kms:DescribeKey", + "kms:ReEncrypt*", + "kms:Decrypt" + ], + "Resource": "${ami_kms_key_arn}" + }, + { + "Effect": "Allow", + "Action": [ + "kms:CreateGrant" + ], + "Resource": "${ami_kms_key_arn}", + "Condition": { + "Bool": { + "aws:ViaAWSService": "true" + } + } %{ endif ~} } ] diff --git a/modules/runners/policies/lambda-ssm-housekeeper.json b/modules/runners/policies/lambda-ssm-housekeeper.json new file mode 100644 index 0000000000..5e49baafaa --- /dev/null +++ b/modules/runners/policies/lambda-ssm-housekeeper.json @@ -0,0 +1,13 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ssm:DeleteParameter", + "ssm:GetParametersByPath" + ], + "Resource": "${ssm_token_path}*" + } + ] +} diff --git a/modules/runners/policies/lambda-vpc.json b/modules/runners/policies/lambda-vpc.json deleted file mode 100644 index 241153d981..0000000000 --- a/modules/runners/policies/lambda-vpc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DeleteNetworkInterface" - ], - "Resource": "*" - } - ] -} diff --git a/modules/runners/pool.tf b/modules/runners/pool.tf index 5200b114e4..fcaa9c698c 100644 --- a/modules/runners/pool.tf +++ b/modules/runners/pool.tf @@ -15,9 +15,9 @@ module "pool" { instance_target_capacity_type = var.instance_target_capacity_type instance_types = var.instance_types kms_key_arn = local.kms_key_arn + ami_kms_key_arn = local.ami_kms_key_arn lambda = { log_level = var.log_level - log_type = var.log_type logging_retention_in_days = var.logging_retention_in_days logging_kms_key_id = var.logging_kms_key_id reserved_concurrent_executions = var.pool_lambda_reserved_concurrent_executions @@ -27,6 +27,7 @@ module "pool" { security_group_ids = var.lambda_security_group_ids subnet_ids = var.lambda_subnet_ids architecture = var.lambda_architecture + memory_size = var.pool_lambda_memory_size runtime = var.lambda_runtime timeout = var.pool_lambda_timeout zip = local.lambda_zip @@ -35,18 +36,28 @@ module "pool" { role_path = local.role_path role_permissions_boundary = var.role_permissions_boundary runner = { - disable_runner_autoupdate = var.disable_runner_autoupdate - ephemeral = var.enable_ephemeral_runners - extra_labels = var.runner_extra_labels - launch_template = aws_launch_template.runner - group_name = var.runner_group_name - pool_owner = var.pool_runner_owner - role = aws_iam_role.runner + disable_runner_autoupdate = var.disable_runner_autoupdate + ephemeral = var.enable_ephemeral_runners + enable_jit_config = var.enable_jit_config + enable_on_demand_failover_for_errors = var.enable_on_demand_failover_for_errors + boot_time_in_minutes = var.runner_boot_time_in_minutes + labels = var.runner_labels + launch_template = aws_launch_template.runner + group_name = var.runner_group_name + name_prefix = var.runner_name_prefix + pool_owner = var.pool_runner_owner + role = aws_iam_role.runner } - subnet_ids = var.subnet_ids - tags = local.tags + subnet_ids = var.subnet_ids + ssm_token_path = "${var.ssm_paths.root}/${var.ssm_paths.tokens}" + ssm_config_path = "${var.ssm_paths.root}/${var.ssm_paths.config}" + ami_id_ssm_parameter_name = var.ami_id_ssm_parameter_name + ami_id_ssm_parameter_read_policy_arn = var.ami_id_ssm_parameter_name != null ? aws_iam_policy.ami_id_ssm_parameter_read[0].arn : null + tags = local.tags + lambda_tags = var.lambda_tags + arn_ssm_parameters_path_config = local.arn_ssm_parameters_path_config } - aws_partition = var.aws_partition - + aws_partition = var.aws_partition + tracing_config = var.tracing_config } diff --git a/modules/runners/pool/README.md b/modules/runners/pool/README.md index 8fc57732b0..1a51a7e7e5 100644 --- a/modules/runners/pool/README.md +++ b/modules/runners/pool/README.md @@ -4,4 +4,56 @@ This module creates the AWS resources required to maintain a pool of runners. Ho ## Why a submodule for the pool -The pool is an opt-in feature. To be able to use the count on a module level to avoid counts per resources a module is created. All inputs of the module are already defined on a higher level. See the mapping of the variables in [`pool.tf`](../pool.tf) \ No newline at end of file +The pool is an opt-in feature. To be able to use the count on a module level to avoid counts per resources a module is created. All inputs of the module are already defined on a higher level. See the mapping of the variables in [`pool.tf`](../pool.tf) + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 0.14.1 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.27 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_event_rule.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_target.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_cloudwatch_log_group.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.pool_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.pool_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.ami_id_ssm_parameter_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.pool_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_lambda_function.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_permission.pool](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_partition](#input\_aws\_partition) | (optional) partition for the arn if not 'aws' | `string` | `"aws"` | no | +| [config](#input\_config) | Lookup details in parent module. |
object({
lambda = object({
log_level = string
logging_retention_in_days = number
logging_kms_key_id = string
reserved_concurrent_executions = number
s3_bucket = string
s3_key = string
s3_object_version = string
security_group_ids = list(string)
runtime = string
architecture = string
memory_size = number
timeout = number
zip = string
subnet_ids = list(string)
})
tags = map(string)
ghes = object({
url = string
ssl_verify = string
})
github_app_parameters = object({
key_base64 = map(string)
id = map(string)
})
subnet_ids = list(string)
runner = object({
disable_runner_autoupdate = bool
ephemeral = bool
enable_jit_config = bool
enable_on_demand_failover_for_errors = list(string)
boot_time_in_minutes = number
labels = list(string)
launch_template = object({
name = string
})
group_name = string
name_prefix = string
pool_owner = string
role = object({
arn = string
})
})
instance_types = list(string)
instance_target_capacity_type = string
instance_allocation_strategy = string
instance_max_spot_price = string
prefix = string
pool = list(object({
schedule_expression = string
size = number
}))
role_permissions_boundary = string
kms_key_arn = string
ami_kms_key_arn = string
role_path = string
ssm_token_path = string
ssm_config_path = string
ami_id_ssm_parameter_name = string
ami_id_ssm_parameter_read_policy_arn = string
arn_ssm_parameters_path_config = string
lambda_tags = map(string)
})
| n/a | yes | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [lambda](#output\_lambda) | n/a | +| [lambda\_log\_group](#output\_lambda\_log\_group) | n/a | +| [role\_pool](#output\_role\_pool) | n/a | + diff --git a/modules/runners/pool/main.tf b/modules/runners/pool/main.tf index c9e65dffe9..cd9b6e9c2b 100644 --- a/modules/runners/pool/main.tf +++ b/modules/runners/pool/main.tf @@ -12,29 +12,40 @@ resource "aws_lambda_function" "pool" { runtime = var.config.lambda.runtime timeout = var.config.lambda.timeout reserved_concurrent_executions = var.config.lambda.reserved_concurrent_executions - memory_size = 512 - tags = var.config.tags + memory_size = var.config.lambda.memory_size + tags = merge(var.config.tags, var.config.lambda_tags) environment { variables = { - DISABLE_RUNNER_AUTOUPDATE = var.config.runner.disable_runner_autoupdate - ENABLE_EPHEMERAL_RUNNERS = var.config.runner.ephemeral - ENVIRONMENT = var.config.prefix - GHES_URL = var.config.ghes.url - INSTANCE_ALLOCATION_STRATEGY = var.config.instance_allocation_strategy - INSTANCE_MAX_SPOT_PRICE = var.config.instance_max_spot_price - INSTANCE_TARGET_CAPACITY_TYPE = var.config.instance_target_capacity_type - INSTANCE_TYPES = join(",", var.config.instance_types) - LAUNCH_TEMPLATE_NAME = var.config.runner.launch_template.name - LOG_LEVEL = var.config.lambda.log_level - LOG_TYPE = var.config.lambda.log_type - NODE_TLS_REJECT_UNAUTHORIZED = var.config.ghes.url != null && !var.config.ghes.ssl_verify ? 0 : 1 - PARAMETER_GITHUB_APP_ID_NAME = var.config.github_app_parameters.id.name - PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.config.github_app_parameters.key_base64.name - RUNNER_EXTRA_LABELS = var.config.runner.extra_labels - RUNNER_GROUP_NAME = var.config.runner.group_name - RUNNER_OWNER = var.config.runner.pool_owner - SUBNET_IDS = join(",", var.config.subnet_ids) + AMI_ID_SSM_PARAMETER_NAME = var.config.ami_id_ssm_parameter_name + DISABLE_RUNNER_AUTOUPDATE = var.config.runner.disable_runner_autoupdate + ENABLE_EPHEMERAL_RUNNERS = var.config.runner.ephemeral + ENABLE_JIT_CONFIG = var.config.runner.enable_jit_config + ENVIRONMENT = var.config.prefix + GHES_URL = var.config.ghes.url + INSTANCE_ALLOCATION_STRATEGY = var.config.instance_allocation_strategy + INSTANCE_MAX_SPOT_PRICE = var.config.instance_max_spot_price + INSTANCE_TARGET_CAPACITY_TYPE = var.config.instance_target_capacity_type + INSTANCE_TYPES = join(",", var.config.instance_types) + LAUNCH_TEMPLATE_NAME = var.config.runner.launch_template.name + LOG_LEVEL = var.config.lambda.log_level + NODE_TLS_REJECT_UNAUTHORIZED = var.config.ghes.url != null && !var.config.ghes.ssl_verify ? 0 : 1 + PARAMETER_GITHUB_APP_ID_NAME = var.config.github_app_parameters.id.name + PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.config.github_app_parameters.key_base64.name + POWERTOOLS_LOGGER_LOG_EVENT = var.config.lambda.log_level == "debug" ? "true" : "false" + RUNNER_BOOT_TIME_IN_MINUTES = var.config.runner.boot_time_in_minutes + RUNNER_LABELS = lower(join(",", var.config.runner.labels)) + RUNNER_GROUP_NAME = var.config.runner.group_name + RUNNER_NAME_PREFIX = var.config.runner.name_prefix + RUNNER_OWNER = var.config.runner.pool_owner + SSM_TOKEN_PATH = var.config.ssm_token_path + SSM_CONFIG_PATH = var.config.ssm_config_path + SUBNET_IDS = join(",", var.config.subnet_ids) + POWERTOOLS_SERVICE_NAME = "runners-pool" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error + ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS = jsonencode(var.config.runner.enable_on_demand_failover_for_errors) } } @@ -45,6 +56,13 @@ resource "aws_lambda_function" "pool" { subnet_ids = var.config.lambda.subnet_ids } } + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } } resource "aws_cloudwatch_log_group" "pool" { @@ -66,10 +84,12 @@ resource "aws_iam_role_policy" "pool" { name = "${var.config.prefix}-lambda-pool-policy" role = aws_iam_role.pool.name policy = templatefile("${path.module}/policies/lambda-pool.json", { - arn_runner_instance_role = var.config.runner.role.arn - github_app_id_arn = var.config.github_app_parameters.id.arn - github_app_key_base64_arn = var.config.github_app_parameters.key_base64.arn - kms_key_arn = var.config.kms_key_arn + arn_ssm_parameters_path_config = var.config.arn_ssm_parameters_path_config + arn_runner_instance_role = var.config.runner.role.arn + github_app_id_arn = var.config.github_app_parameters.id.arn + github_app_key_base64_arn = var.config.github_app_parameters.key_base64.arn + kms_key_arn = var.config.kms_key_arn + ami_kms_key_arn = var.config.ami_kms_key_arn }) } @@ -81,14 +101,6 @@ resource "aws_iam_role_policy" "pool_logging" { }) } -resource "aws_iam_role_policy" "lambda_pool_vpc" { - count = length(var.config.lambda.subnet_ids) > 0 && length(var.config.lambda.security_group_ids) > 0 ? 1 : 0 - name = "${var.config.prefix}-lambda-pool-vpc" - role = aws_iam_role.pool.id - - policy = file("${path.module}/../policies/lambda-vpc.json") -} - resource "aws_iam_role_policy_attachment" "pool_vpc_execution_role" { count = length(var.config.lambda.subnet_ids) > 0 ? 1 : 0 role = aws_iam_role.pool.name @@ -135,3 +147,33 @@ resource "aws_lambda_permission" "pool" { principal = "events.amazonaws.com" source_arn = aws_cloudwatch_event_rule.pool[count.index].arn } + +resource "aws_iam_role_policy_attachment" "ami_id_ssm_parameter_read" { + count = var.config.ami_id_ssm_parameter_name != null ? 1 : 0 + role = aws_iam_role.pool.name + policy_arn = var.config.ami_id_ssm_parameter_read_policy_arn +} + +# lambda xray policy +data "aws_iam_policy_document" "lambda_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + statement { + actions = [ + "xray:BatchGetTraces", + "xray:GetTraceSummaries", + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ] + effect = "Allow" + resources = [ + "*" + ] + sid = "AllowXRay" + } +} + +resource "aws_iam_role_policy" "pool_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.pool.name +} diff --git a/modules/runners/pool/outputs.tf b/modules/runners/pool/outputs.tf index e9c5aac8f8..7a4d70ca9f 100644 --- a/modules/runners/pool/outputs.tf +++ b/modules/runners/pool/outputs.tf @@ -1,3 +1,11 @@ output "role_pool" { value = aws_iam_role.pool } + +output "lambda" { + value = aws_lambda_function.pool +} + +output "lambda_log_group" { + value = aws_cloudwatch_log_group.pool +} diff --git a/modules/runners/pool/policies/lambda-pool.json b/modules/runners/pool/policies/lambda-pool.json index 3e00cec501..f8e3f39a23 100644 --- a/modules/runners/pool/policies/lambda-pool.json +++ b/modules/runners/pool/policies/lambda-pool.json @@ -22,10 +22,23 @@ { "Effect": "Allow", "Action": [ + "ssm:AddTagsToResource", "ssm:PutParameter" ], "Resource": "*" }, + { + "Effect": "Allow", + "Action": [ + "ssm:GetParameter", + "ssm:GetParameters", + "ssm:GetParametersByPath" + ], + "Resource": [ + "${arn_ssm_parameters_path_config}", + "${arn_ssm_parameters_path_config}/*" + ] + }, { "Effect": "Allow", "Action": [ @@ -43,6 +56,29 @@ "kms:Decrypt" ], "Resource": "${kms_key_arn}" +%{ endif ~} +%{ if ami_kms_key_arn != "" ~} + }, + { + "Effect": "Allow", + "Action": [ + "kms:DescribeKey", + "kms:ReEncrypt*", + "kms:Decrypt" + ], + "Resource": "${ami_kms_key_arn}" + }, + { + "Effect": "Allow", + "Action": [ + "kms:CreateGrant" + ], + "Resource": "${ami_kms_key_arn}", + "Condition": { + "Bool": { + "aws:ViaAWSService": "true" + } + } %{ endif ~} } ] diff --git a/modules/runners/pool/variables.tf b/modules/runners/pool/variables.tf index 064da4a70c..a60c002fd9 100644 --- a/modules/runners/pool/variables.tf +++ b/modules/runners/pool/variables.tf @@ -1,8 +1,8 @@ variable "config" { + description = "Lookup details in parent module." type = object({ lambda = object({ log_level = string - log_type = string logging_retention_in_days = number logging_kms_key_id = string reserved_concurrent_executions = number @@ -12,6 +12,7 @@ variable "config" { security_group_ids = list(string) runtime = string architecture = string + memory_size = number timeout = number zip = string subnet_ids = list(string) @@ -27,14 +28,18 @@ variable "config" { }) subnet_ids = list(string) runner = object({ - disable_runner_autoupdate = bool - ephemeral = bool - extra_labels = string + disable_runner_autoupdate = bool + ephemeral = bool + enable_jit_config = bool + enable_on_demand_failover_for_errors = list(string) + boot_time_in_minutes = number + labels = list(string) launch_template = object({ name = string }) - group_name = string - pool_owner = string + group_name = string + name_prefix = string + pool_owner = string role = object({ arn = string }) @@ -48,9 +53,16 @@ variable "config" { schedule_expression = string size = number })) - role_permissions_boundary = string - kms_key_arn = string - role_path = string + role_permissions_boundary = string + kms_key_arn = string + ami_kms_key_arn = string + role_path = string + ssm_token_path = string + ssm_config_path = string + ami_id_ssm_parameter_name = string + ami_id_ssm_parameter_read_policy_arn = string + arn_ssm_parameters_path_config = string + lambda_tags = map(string) }) } @@ -59,3 +71,15 @@ variable "aws_partition" { type = string default = "aws" } + +variable "tracing_config" { + description = "Configuration for lambda tracing." + type = object({ + mode = optional(string, null) + capture_http_requests = optional(bool, false) + capture_error = optional(bool, false) + }) + default = {} +} + + diff --git a/modules/runners/pool/versions.tf b/modules/runners/pool/versions.tf new file mode 100644 index 0000000000..49fc685a01 --- /dev/null +++ b/modules/runners/pool/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.14.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.27" + } + } +} diff --git a/modules/runners/runner-config.tf b/modules/runners/runner-config.tf index e4745a1a9a..684873a7ff 100644 --- a/modules/runners/runner-config.tf +++ b/modules/runners/runner-config.tf @@ -1,20 +1,34 @@ resource "aws_ssm_parameter" "runner_config_run_as" { - name = "/${var.prefix}/runner/run-as" + name = "${var.ssm_paths.root}/${var.ssm_paths.config}/run_as" type = "String" value = var.runner_as_root ? "root" : var.runner_run_as tags = local.tags } resource "aws_ssm_parameter" "runner_agent_mode" { - name = "/${var.prefix}/runner/agent-mode" + name = "${var.ssm_paths.root}/${var.ssm_paths.config}/agent_mode" type = "String" value = var.enable_ephemeral_runners ? "ephemeral" : "persistent" tags = local.tags } +resource "aws_ssm_parameter" "jit_config_enabled" { + name = "${var.ssm_paths.root}/${var.ssm_paths.config}/enable_jit_config" + type = "String" + value = var.enable_jit_config == null ? var.enable_ephemeral_runners : var.enable_jit_config + tags = local.tags +} + resource "aws_ssm_parameter" "runner_enable_cloudwatch" { - name = "/${var.prefix}/runner/enable-cloudwatch" + name = "${var.ssm_paths.root}/${var.ssm_paths.config}/enable_cloudwatch" type = "String" value = var.enable_cloudwatch_agent tags = local.tags } + +resource "aws_ssm_parameter" "token_path" { + name = "${var.ssm_paths.root}/${var.ssm_paths.config}/token_path" + type = "String" + value = "${var.ssm_paths.root}/${var.ssm_paths.tokens}" + tags = local.tags +} diff --git a/modules/runners/scale-down.tf b/modules/runners/scale-down.tf index 69f26b9218..c74f88e387 100644 --- a/modules/runners/scale-down.tf +++ b/modules/runners/scale-down.tf @@ -16,22 +16,26 @@ resource "aws_lambda_function" "scale_down" { handler = "index.scaleDownHandler" runtime = var.lambda_runtime timeout = var.lambda_timeout_scale_down - tags = local.tags - memory_size = 512 + tags = merge(local.tags, var.lambda_tags) + memory_size = var.lambda_scale_down_memory_size architectures = [var.lambda_architecture] environment { variables = { - ENVIRONMENT = var.prefix - GHES_URL = var.ghes_url - LOG_LEVEL = var.log_level - LOG_TYPE = var.log_type - MINIMUM_RUNNING_TIME_IN_MINUTES = coalesce(var.minimum_running_time_in_minutes, local.min_runtime_defaults[var.runner_os]) - NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && !var.ghes_ssl_verify ? 0 : 1 - PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name - PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.github_app_parameters.key_base64.name - RUNNER_BOOT_TIME_IN_MINUTES = var.runner_boot_time_in_minutes - SCALE_DOWN_CONFIG = jsonencode(var.idle_config) + ENVIRONMENT = var.prefix + GHES_URL = var.ghes_url + LOG_LEVEL = var.log_level + MINIMUM_RUNNING_TIME_IN_MINUTES = coalesce(var.minimum_running_time_in_minutes, local.min_runtime_defaults[var.runner_os]) + NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && !var.ghes_ssl_verify ? 0 : 1 + PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name + PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.github_app_parameters.key_base64.name + POWERTOOLS_LOGGER_LOG_EVENT = var.log_level == "debug" ? "true" : "false" + RUNNER_BOOT_TIME_IN_MINUTES = var.runner_boot_time_in_minutes + SCALE_DOWN_CONFIG = jsonencode(var.idle_config) + POWERTOOLS_SERVICE_NAME = "runners-scale-down" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error } } @@ -42,6 +46,13 @@ resource "aws_lambda_function" "scale_down" { subnet_ids = var.lambda_subnet_ids } } + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } } resource "aws_cloudwatch_log_group" "scale_down" { @@ -96,16 +107,14 @@ resource "aws_iam_role_policy" "scale_down_logging" { }) } -resource "aws_iam_role_policy" "lambda_scale_down_vpc" { - count = length(var.lambda_subnet_ids) > 0 && length(var.lambda_security_group_ids) > 0 ? 1 : 0 - name = "${var.prefix}-lambda-scale-down-vpc" - role = aws_iam_role.scale_down.id - - policy = file("${path.module}/policies/lambda-vpc.json") -} - resource "aws_iam_role_policy_attachment" "scale_down_vpc_execution_role" { count = length(var.lambda_subnet_ids) > 0 ? 1 : 0 role = aws_iam_role.scale_down.name policy_arn = "arn:${var.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" } + +resource "aws_iam_role_policy" "scale_down_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.scale_down.name +} diff --git a/modules/runners/scale-up.tf b/modules/runners/scale-up.tf index 80c4614f84..cd3fd2c9b5 100644 --- a/modules/runners/scale-up.tf +++ b/modules/runners/scale-up.tf @@ -10,33 +10,42 @@ resource "aws_lambda_function" "scale_up" { runtime = var.lambda_runtime timeout = var.lambda_timeout_scale_up reserved_concurrent_executions = var.scale_up_reserved_concurrent_executions - memory_size = 512 - tags = local.tags + memory_size = var.lambda_scale_up_memory_size + tags = merge(local.tags, var.lambda_tags) architectures = [var.lambda_architecture] - environment { variables = { - DISABLE_RUNNER_AUTOUPDATE = var.disable_runner_autoupdate - ENABLE_EPHEMERAL_RUNNERS = var.enable_ephemeral_runners - ENABLE_JOB_QUEUED_CHECK = local.enable_job_queued_check - ENABLE_ORGANIZATION_RUNNERS = var.enable_organization_runners - ENVIRONMENT = var.prefix - GHES_URL = var.ghes_url - INSTANCE_ALLOCATION_STRATEGY = var.instance_allocation_strategy - INSTANCE_MAX_SPOT_PRICE = var.instance_max_spot_price - INSTANCE_TARGET_CAPACITY_TYPE = var.instance_target_capacity_type - INSTANCE_TYPES = join(",", var.instance_types) - LAUNCH_TEMPLATE_NAME = aws_launch_template.runner.name - LOG_LEVEL = var.log_level - LOG_TYPE = var.log_type - NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && !var.ghes_ssl_verify ? 0 : 1 - PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name - PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.github_app_parameters.key_base64.name - RUNNER_EXTRA_LABELS = lower(var.runner_extra_labels) - RUNNER_GROUP_NAME = var.runner_group_name - RUNNERS_MAXIMUM_COUNT = var.runners_maximum_count - SUBNET_IDS = join(",", var.subnet_ids) - AMI_ID_SSM_PARAMETER_NAME = var.ami_id_ssm_parameter_name + AMI_ID_SSM_PARAMETER_NAME = var.ami_id_ssm_parameter_name + DISABLE_RUNNER_AUTOUPDATE = var.disable_runner_autoupdate + ENABLE_EPHEMERAL_RUNNERS = var.enable_ephemeral_runners + ENABLE_JIT_CONFIG = var.enable_jit_config + ENABLE_JOB_QUEUED_CHECK = local.enable_job_queued_check + ENABLE_ORGANIZATION_RUNNERS = var.enable_organization_runners + ENVIRONMENT = var.prefix + GHES_URL = var.ghes_url + INSTANCE_ALLOCATION_STRATEGY = var.instance_allocation_strategy + INSTANCE_MAX_SPOT_PRICE = var.instance_max_spot_price + INSTANCE_TARGET_CAPACITY_TYPE = var.instance_target_capacity_type + INSTANCE_TYPES = join(",", var.instance_types) + LAUNCH_TEMPLATE_NAME = aws_launch_template.runner.name + LOG_LEVEL = var.log_level + MINIMUM_RUNNING_TIME_IN_MINUTES = coalesce(var.minimum_running_time_in_minutes, local.min_runtime_defaults[var.runner_os]) + NODE_TLS_REJECT_UNAUTHORIZED = var.ghes_url != null && !var.ghes_ssl_verify ? 0 : 1 + PARAMETER_GITHUB_APP_ID_NAME = var.github_app_parameters.id.name + PARAMETER_GITHUB_APP_KEY_BASE64_NAME = var.github_app_parameters.key_base64.name + POWERTOOLS_LOGGER_LOG_EVENT = var.log_level == "debug" ? "true" : "false" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error + RUNNER_LABELS = lower(join(",", var.runner_labels)) + RUNNER_GROUP_NAME = var.runner_group_name + RUNNER_NAME_PREFIX = var.runner_name_prefix + RUNNERS_MAXIMUM_COUNT = var.runners_maximum_count + POWERTOOLS_SERVICE_NAME = "runners-scale-up" + SSM_TOKEN_PATH = local.token_path + SSM_CONFIG_PATH = "${var.ssm_paths.root}/${var.ssm_paths.config}" + SUBNET_IDS = join(",", var.subnet_ids) + ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS = jsonencode(var.enable_on_demand_failover_for_errors) } } @@ -47,6 +56,13 @@ resource "aws_lambda_function" "scale_up" { subnet_ids = var.lambda_subnet_ids } } + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } } resource "aws_cloudwatch_log_group" "scale_up" { @@ -86,7 +102,9 @@ resource "aws_iam_role_policy" "scale_up" { sqs_arn = var.sqs_build_queue.arn github_app_id_arn = var.github_app_parameters.id.arn github_app_key_base64_arn = var.github_app_parameters.key_base64.arn + ssm_config_path = "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${var.ssm_paths.root}/${var.ssm_paths.config}" kms_key_arn = local.kms_key_arn + ami_kms_key_arn = local.ami_kms_key_arn }) } @@ -106,38 +124,20 @@ resource "aws_iam_role_policy" "service_linked_role" { policy = templatefile("${path.module}/policies/service-linked-role-create-policy.json", { aws_partition = var.aws_partition }) } -resource "aws_iam_role_policy" "lambda_scale_up_vpc" { - count = length(var.lambda_subnet_ids) > 0 && length(var.lambda_security_group_ids) > 0 ? 1 : 0 - name = "${var.prefix}-lambda-scale-up-vpc" - role = aws_iam_role.scale_up.id - - policy = file("${path.module}/policies/lambda-vpc.json") -} - resource "aws_iam_role_policy_attachment" "scale_up_vpc_execution_role" { count = length(var.lambda_subnet_ids) > 0 ? 1 : 0 role = aws_iam_role.scale_up.name policy_arn = "arn:${var.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" } -resource "aws_iam_role_policy" "ami_id_ssm_parameter_read" { - count = var.ami_id_ssm_parameter_name != null ? 1 : 0 - name = "${var.prefix}-ami-id-ssm-parameter-read" +resource "aws_iam_role_policy_attachment" "ami_id_ssm_parameter_read" { + count = var.ami_id_ssm_parameter_name != null ? 1 : 0 + role = aws_iam_role.scale_up.name + policy_arn = aws_iam_policy.ami_id_ssm_parameter_read[0].arn +} + +resource "aws_iam_role_policy" "scale_up_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json role = aws_iam_role.scale_up.name - policy = <<-JSON - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "ssm:GetParameter" - ], - "Resource": [ - "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter/${trimprefix(var.ami_id_ssm_parameter_name, "/")}" - ] - } - ] - } - JSON } diff --git a/modules/runners/ssm-housekeeper.tf b/modules/runners/ssm-housekeeper.tf new file mode 100644 index 0000000000..64a63ed92d --- /dev/null +++ b/modules/runners/ssm-housekeeper.tf @@ -0,0 +1,120 @@ +locals { + ssm_housekeeper = { + schedule_expression = var.ssm_housekeeper.schedule_expression + state = var.ssm_housekeeper.state + lambda_timeout = var.ssm_housekeeper.lambda_timeout + lambda_memory_size = var.ssm_housekeeper.lambda_memory_size + config = { + tokenPath = var.ssm_housekeeper.config.tokenPath == null ? local.token_path : var.ssm_housekeeper.config.tokenPath + minimumDaysOld = var.ssm_housekeeper.config.minimumDaysOld + dryRun = var.ssm_housekeeper.config.dryRun + } + } +} + +resource "aws_lambda_function" "ssm_housekeeper" { + s3_bucket = var.lambda_s3_bucket != null ? var.lambda_s3_bucket : null + s3_key = var.runners_lambda_s3_key != null ? var.runners_lambda_s3_key : null + s3_object_version = var.runners_lambda_s3_object_version != null ? var.runners_lambda_s3_object_version : null + filename = var.lambda_s3_bucket == null ? local.lambda_zip : null + source_code_hash = var.lambda_s3_bucket == null ? filebase64sha256(local.lambda_zip) : null + function_name = "${var.prefix}-ssm-housekeeper" + role = aws_iam_role.ssm_housekeeper.arn + handler = "index.ssmHousekeeper" + runtime = var.lambda_runtime + timeout = local.ssm_housekeeper.lambda_timeout + tags = merge(local.tags, var.lambda_tags) + memory_size = local.ssm_housekeeper.lambda_memory_size + architectures = [var.lambda_architecture] + + environment { + variables = { + ENVIRONMENT = var.prefix + LOG_LEVEL = var.log_level + SSM_CLEANUP_CONFIG = jsonencode(local.ssm_housekeeper.config) + POWERTOOLS_SERVICE_NAME = "ssm-housekeeper" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error + } + } + + dynamic "vpc_config" { + for_each = var.lambda_subnet_ids != null && var.lambda_security_group_ids != null ? [true] : [] + content { + security_group_ids = var.lambda_security_group_ids + subnet_ids = var.lambda_subnet_ids + } + } + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } +} + +resource "aws_cloudwatch_log_group" "ssm_housekeeper" { + name = "/aws/lambda/${aws_lambda_function.ssm_housekeeper.function_name}" + retention_in_days = var.logging_retention_in_days + kms_key_id = var.logging_kms_key_id + tags = var.tags +} + +resource "aws_cloudwatch_event_rule" "ssm_housekeeper" { + name = "${var.prefix}-ssm-housekeeper" + schedule_expression = local.ssm_housekeeper.schedule_expression + tags = var.tags + state = local.ssm_housekeeper.state +} + +resource "aws_cloudwatch_event_target" "ssm_housekeeper" { + rule = aws_cloudwatch_event_rule.ssm_housekeeper.name + arn = aws_lambda_function.ssm_housekeeper.arn +} + +resource "aws_lambda_permission" "ssm_housekeeper" { + statement_id = "AllowExecutionFromCloudWatch" + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.ssm_housekeeper.function_name + principal = "events.amazonaws.com" + source_arn = aws_cloudwatch_event_rule.ssm_housekeeper.arn +} + +resource "aws_iam_role" "ssm_housekeeper" { + name = "${var.prefix}-ssm-hk-lambda" + description = "Lambda role for SSM Housekeeper (${var.prefix})" + assume_role_policy = data.aws_iam_policy_document.lambda_assume_role_policy.json + path = local.role_path + permissions_boundary = var.role_permissions_boundary + tags = local.tags +} + +resource "aws_iam_role_policy" "ssm_housekeeper" { + name = "lambda-ssm" + role = aws_iam_role.ssm_housekeeper.name + policy = templatefile("${path.module}/policies/lambda-ssm-housekeeper.json", { + ssm_token_path = "arn:${var.aws_partition}:ssm:${var.aws_region}:${data.aws_caller_identity.current.account_id}:parameter${local.token_path}" + }) +} + +resource "aws_iam_role_policy" "ssm_housekeeper_logging" { + name = "lambda-logging" + role = aws_iam_role.ssm_housekeeper.name + policy = templatefile("${path.module}/policies/lambda-cloudwatch.json", { + log_group_arn = aws_cloudwatch_log_group.ssm_housekeeper.arn + }) +} + +resource "aws_iam_role_policy_attachment" "ssm_housekeeper_vpc_execution_role" { + count = length(var.lambda_subnet_ids) > 0 ? 1 : 0 + role = aws_iam_role.ssm_housekeeper.name + policy_arn = "arn:${var.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" +} + +resource "aws_iam_role_policy" "ssm_housekeeper_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.ssm_housekeeper.name +} diff --git a/modules/runners/templates/install-runner.sh b/modules/runners/templates/install-runner.sh index 130cb9be54..7cda0c5568 100644 --- a/modules/runners/templates/install-runner.sh +++ b/modules/runners/templates/install-runner.sh @@ -42,11 +42,28 @@ tar xzf ./$file_name echo "Delete tar file" rm -rf $file_name -if [[ "$architecture" == "arm64" ]]; then - yum install -y libicu60 +os_id=$(awk -F= '/^ID/{print $2}' /etc/os-release) +echo OS: $os_id + +# Install libicu on non-ubuntu +if [[ ! "$os_id" =~ ^ubuntu.* ]]; then + max_attempts=5 + attempt_count=0 + success=false + while [ $success = false ] && [ $attempt_count -le $max_attempts ]; do + echo "Attempt $attempt_count/$max_attempts: Installing libicu" + dnf install -y libicu + if [ $? -eq 0 ]; then + success=true + else + echo "Failed to install libicu" + attempt_count=$(( attempt_count + 1 )) + sleep 5 + fi + done fi -os_id=$(awk -F= '/^ID/{print $2}' /etc/os-release) +# Install dependencies for ubuntu if [[ "$os_id" =~ ^ubuntu.* ]]; then echo "Installing dependencies" ./bin/installdependencies.sh diff --git a/modules/runners/templates/start-runner.ps1 b/modules/runners/templates/start-runner.ps1 index 3271652a0c..5046d3e9dd 100644 --- a/modules/runners/templates/start-runner.ps1 +++ b/modules/runners/templates/start-runner.ps1 @@ -3,39 +3,62 @@ Write-Host "Retrieving TOKEN from AWS API" $token=Invoke-RestMethod -Method PUT -Uri "http://169.254.169.254/latest/api/token" -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "180"} +if ( ! $token ) { + $retrycount=0 + do { + echo "Failed to retrieve token. Retrying in 5 seconds." + Start-Sleep 5 + $token=Invoke-RestMethod -Method PUT -Uri "http://169.254.169.254/latest/api/token" -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "180"} + $retrycount=$retrycount + 1 + if ( $retrycount -gt 40 ) + { + break + } + } until ($token) +} $ami_id=Invoke-RestMethod -Uri "http://169.254.169.254/latest/meta-data/ami-id" -Headers @{"X-aws-ec2-metadata-token" = $token} $metadata=Invoke-RestMethod -Uri "http://169.254.169.254/latest/dynamic/instance-identity/document" -Headers @{"X-aws-ec2-metadata-token" = $token} $Region = $metadata.region -Write-Host "Reteieved REGION from AWS API ($Region)" +Write-Host "Retrieved REGION from AWS API ($Region)" $InstanceId = $metadata.instanceId -Write-Host "Reteieved InstanceId from AWS API ($InstanceId)" +Write-Host "Retrieved InstanceId from AWS API ($InstanceId)" $tags=aws ec2 describe-tags --region "$Region" --filters "Name=resource-id,Values=$InstanceId" | ConvertFrom-Json Write-Host "Retrieved tags from AWS API" $environment=$tags.Tags.where( {$_.Key -eq 'ghr:environment'}).value -Write-Host "Reteieved ghr:environment tag - ($environment)" +Write-Host "Retrieved ghr:environment tag - ($environment)" + +$runner_name_prefix=$tags.Tags.where( {$_.Key -eq 'ghr:runner_name_prefix'}).value +Write-Host "Retrieved ghr:runner_name_prefix tag - ($runner_name_prefix)" -$parameters=$(aws ssm get-parameters-by-path --path "/$environment/runner" --region "$Region" --query "Parameters[*].{Name:Name,Value:Value}") | ConvertFrom-Json +$ssm_config_path=$tags.Tags.where( {$_.Key -eq 'ghr:ssm_config_path'}).value +Write-Host "Retrieved ghr:ssm_config_path tag - ($ssm_config_path)" + +$parameters=$(aws ssm get-parameters-by-path --path "$ssm_config_path" --region "$Region" --query "Parameters[*].{Name:Name,Value:Value}") | ConvertFrom-Json Write-Host "Retrieved parameters from AWS SSM" -$run_as=$parameters.where( {$_.Name -eq "/$environment/runner/run-as"}).value -Write-Host "Retrieved /$environment/runner/run-as parameter - ($run_as)" +$run_as=$parameters.where( {$_.Name -eq "$ssm_config_path/run_as"}).value +Write-Host "Retrieved $ssm_config_path/run_as parameter - ($run_as)" + +$enable_cloudwatch_agent=$parameters.where( {$_.Name -eq "$ssm_config_path/enable_cloudwatch"}).value +Write-Host "Retrieved $ssm_config_path/enable_cloudwatch parameter - ($enable_cloudwatch_agent)" + +$agent_mode=$parameters.where( {$_.Name -eq "$ssm_config_path/agent_mode"}).value +Write-Host "Retrieved $ssm_config_path/agent_mode parameter - ($agent_mode)" -$enable_cloudwatch_agent=$parameters.where( {$_.Name -eq "/$environment/runner/enable-cloudwatch"}).value -Write-Host "Retrieved /$environment/runner/enable-cloudwatch parameter - ($enable_cloudwatch_agent)" +$token_path=$parameters.where( {$_.Name -eq "$ssm_config_path/token_path"}).value +Write-Host "Retrieved $ssm_config_path/token_path parameter - ($token_path)" -$agent_mode=$parameters.where( {$_.Name -eq "/$environment/runner/agent-mode"}).value -Write-Host "Retrieved /$environment/runner/agent-mode parameter - ($agent_mode)" if ($enable_cloudwatch_agent -eq "true") { Write-Host "Enabling CloudWatch Agent" - & 'C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1' -a fetch-config -m ec2 -s -c "ssm:$environment-cloudwatch_agent_config_runner" + & 'C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1' -a fetch-config -m ec2 -s -c "ssm:$ssm_config_path/cloudwatch_agent_config_runner" } ## Configure the runner @@ -44,14 +67,14 @@ Write-Host "Get GH Runner config from AWS SSM" $config = $null $i = 0 do { - $config = (aws ssm get-parameters --names "$environment-$InstanceId" --with-decryption --region $Region --query "Parameters[*].{Name:Name,Value:Value}" | ConvertFrom-Json)[0].value + $config = (aws ssm get-parameters --names "$token_path/$InstanceId" --with-decryption --region $Region --query "Parameters[*].{Name:Name,Value:Value}" | ConvertFrom-Json)[0].value Write-Host "Waiting for GH Runner config to become available in AWS SSM ($i/30)" Start-Sleep 1 $i++ } while (($null -eq $config) -and ($i -lt 30)) Write-Host "Delete GH Runner token from AWS SSM" -aws ssm delete-parameter --name "$environment-$InstanceId" --region $Region +aws ssm delete-parameter --name "$token_path/$InstanceId" --region $Region # Create or update user if (-not($run_as)) { @@ -84,7 +107,7 @@ foreach ($group in @("Administrators", "docker-users")) { Set-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name ConsentPromptBehaviorAdmin -Value 0 -Force Write-Host "Disabled User Access Control (UAC)" -$configCmd = ".\config.cmd --unattended --name $InstanceId --work `"_work`" $config" +$configCmd = ".\config.cmd --unattended --name $runner_name_prefix$InstanceId --work `"_work`" $config" Write-Host "Configure GH Runner as user $run_as" Invoke-Expression $configCmd @@ -93,7 +116,7 @@ Write-Host "Starting the runner as user $run_as" $jsonBody = @( @{ group='Runner Image' - details="AMI id: $ami_id" + detail="AMI id: $ami_id" } ) ConvertTo-Json -InputObject $jsonBody | Set-Content -Path "$pwd\.setup_info" diff --git a/modules/runners/templates/start-runner.sh b/modules/runners/templates/start-runner.sh index 8acb878d0f..0ebd75deb1 100644 --- a/modules/runners/templates/start-runner.sh +++ b/modules/runners/templates/start-runner.sh @@ -1,9 +1,101 @@ -# shellcheck shell=bash - -## Retrieve instance metadata +#!/bin/bash + +# https://docs.aws.amazon.com/xray/latest/devguide/xray-api-sendingdata.html +# https://docs.aws.amazon.com/xray/latest/devguide/scorekeep-scripts.html +create_xray_start_segment() { + START_TIME=$(date -d "$(uptime -s)" +%s) + TRACE_ID=$1 + INSTANCE_ID=$2 + SEGMENT_ID=$(dd if=/dev/random bs=8 count=1 2>/dev/null | od -An -tx1 | tr -d ' \t\n') + SEGMENT_DOC="{\"trace_id\": \"$TRACE_ID\", \"id\": \"$SEGMENT_ID\", \"start_time\": $START_TIME, \"in_progress\": true, \"name\": \"Runner\",\"origin\": \"AWS::EC2::Instance\", \"aws\": {\"ec2\":{\"instance_id\":\"$INSTANCE_ID\"}}}" + HEADER='{"format": "json", "version": 1}' + TRACE_DATA="$HEADER\n$SEGMENT_DOC" + echo "$HEADER" > document.txt + echo "$SEGMENT_DOC" >> document.txt + UDP_IP="127.0.0.1" + UDP_PORT=2000 + cat document.txt > /dev/udp/$UDP_IP/$UDP_PORT + echo "$SEGMENT_DOC" +} + +create_xray_success_segment() { + local SEGMENT_DOC=$1 + if [ -z "$SEGMENT_DOC" ]; then + echo "No segment doc provided" + return + fi + SEGMENT_DOC=$(echo "$SEGMENT_DOC" | jq '. | del(.in_progress)') + END_TIME=$(date +%s) + SEGMENT_DOC=$(echo "$SEGMENT_DOC" | jq -c ". + {\"end_time\": $END_TIME}") + HEADER="{\"format\": \"json\", \"version\": 1}" + TRACE_DATA="$HEADER\n$SEGMENT_DOC" + echo "$HEADER" > document.txt + echo "$SEGMENT_DOC" >> document.txt + UDP_IP="127.0.0.1" + UDP_PORT=2000 + cat document.txt > /dev/udp/$UDP_IP/$UDP_PORT + echo "$SEGMENT_DOC" +} + +create_xray_error_segment() { + local SEGMENT_DOC="$1" + if [ -z "$SEGMENT_DOC" ]; then + echo "No segment doc provided" + return + fi + MESSAGE="$2" + ERROR="{\"exceptions\": [{\"message\": \"$MESSAGE\"}]}" + SEGMENT_DOC=$(echo "$SEGMENT_DOC" | jq '. | del(.in_progress)') + END_TIME=$(date +%s) + SEGMENT_DOC=$(echo "$SEGMENT_DOC" | jq -c ". + {\"end_time\": $END_TIME, \"error\": true, \"cause\": $ERROR }") + HEADER="{\"format\": \"json\", \"version\": 1}" + TRACE_DATA="$HEADER\n$SEGMENT_DOC" + echo "$HEADER" > document.txt + echo "$SEGMENT_DOC" >> document.txt + UDP_IP="127.0.0.1" + UDP_PORT=2000 + cat document.txt > /dev/udp/$UDP_IP/$UDP_PORT + echo "$SEGMENT_DOC" +} + +cleanup() { + local exit_code="$1" + local error_location="$2" + local error_lineno="$3" + + if [ "$exit_code" -ne 0 ]; then + echo "ERROR: runner-start-failed with exit code $exit_code occurred on $error_location" + create_xray_error_segment "$SEGMENT" "runner-start-failed with exit code $exit_code occurred on $error_location - $error_lineno" + fi + # allows to flush the cloud watch logs and traces + sleep 10 + if [ "$agent_mode" = "ephemeral" ] || [ "$exit_code" -ne 0 ]; then + echo "Stopping CloudWatch service" + systemctl stop amazon-cloudwatch-agent.service || true + echo "Terminating instance" + aws ec2 terminate-instances \ + --instance-ids "$instance_id" \ + --region "$region" \ + || true + fi +} + +trap 'cleanup $? $LINENO $BASH_LINENO' EXIT echo "Retrieving TOKEN from AWS API" -token=$(curl -f -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 180") +token=$(curl -f -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 180" || true) +if [ -z "$token" ]; then + retrycount=0 + until [ -n "$token" ]; do + echo "Failed to retrieve token. Retrying in 5 seconds." + sleep 5 + token=$(curl -f -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 180" || true) + retrycount=$((retrycount + 1)) + if [ $retrycount -gt 40 ]; then + break + fi + done +fi ami_id=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/ami-id) @@ -13,39 +105,77 @@ echo "Retrieved REGION from AWS API ($region)" instance_id=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/instance-id) echo "Retrieved INSTANCE_ID from AWS API ($instance_id)" +instance_type=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/instance-type) +availability_zone=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/placement/availability-zone) + +%{ if metadata_tags == "enabled" } environment=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/tags/instance/ghr:environment) +ssm_config_path=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/tags/instance/ghr:ssm_config_path) +runner_name_prefix=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/tags/instance/ghr:runner_name_prefix || echo "") +xray_trace_id=$(curl -f -H "X-aws-ec2-metadata-token: $token" -v http://169.254.169.254/latest/meta-data/tags/instance/ghr:trace_id || echo "") + +%{ else } +tags=$(aws ec2 describe-tags --region "$region" --filters "Name=resource-id,Values=$instance_id") +echo "Retrieved tags from AWS API ($tags)" + +environment=$(echo "$tags" | jq -r '.Tags[] | select(.Key == "ghr:environment") | .Value') +ssm_config_path=$(echo "$tags" | jq -r '.Tags[] | select(.Key == "ghr:ssm_config_path") | .Value') +runner_name_prefix=$(echo "$tags" | jq -r '.Tags[] | select(.Key == "ghr:runner_name_prefix") | .Value' || echo "") +xray_trace_id=$(echo "$tags" | jq -r '.Tags[] | select(.Key == "ghr:trace_id") | .Value' || echo "") + +%{ endif } + echo "Retrieved ghr:environment tag - ($environment)" +echo "Retrieved ghr:ssm_config_path tag - ($ssm_config_path)" +echo "Retrieved ghr:runner_name_prefix tag - ($runner_name_prefix)" -parameters=$(aws ssm get-parameters-by-path --path "/$environment/runner" --region "$region" --query "Parameters[*].{Name:Name,Value:Value}") +parameters=$(aws ssm get-parameters-by-path --path "$ssm_config_path" --region "$region" --query "Parameters[*].{Name:Name,Value:Value}") echo "Retrieved parameters from AWS SSM ($parameters)" -run_as=$(echo "$parameters" | jq --arg environment "$environment" -r '.[] | select(.Name == "/\($environment)/runner/run-as") | .Value') -echo "Retrieved /$environment/runner/run-as parameter - ($run_as)" +run_as=$(echo "$parameters" | jq -r '.[] | select(.Name == "'$ssm_config_path'/run_as") | .Value') +echo "Retrieved /$ssm_config_path/run_as parameter - ($run_as)" + +enable_cloudwatch_agent=$(echo "$parameters" | jq --arg ssm_config_path "$ssm_config_path" -r '.[] | select(.Name == "'$ssm_config_path'/enable_cloudwatch") | .Value') +echo "Retrieved /$ssm_config_path/enable_cloudwatch parameter - ($enable_cloudwatch_agent)" + +agent_mode=$(echo "$parameters" | jq --arg ssm_config_path "$ssm_config_path" -r '.[] | select(.Name == "'$ssm_config_path'/agent_mode") | .Value') +echo "Retrieved /$ssm_config_path/agent_mode parameter - ($agent_mode)" + +enable_jit_config=$(echo "$parameters" | jq --arg ssm_config_path "$ssm_config_path" -r '.[] | select(.Name == "'$ssm_config_path'/enable_jit_config") | .Value') +echo "Retrieved /$ssm_config_path/enable_jit_config parameter - ($enable_jit_config)" + +token_path=$(echo "$parameters" | jq --arg ssm_config_path "$ssm_config_path" -r '.[] | select(.Name == "'$ssm_config_path'/token_path") | .Value') +echo "Retrieved /$ssm_config_path/token_path parameter - ($token_path)" + +if [[ "$xray_trace_id" != "" ]]; then + # run xray service + curl https://s3.us-east-2.amazonaws.com/aws-xray-assets.us-east-2/xray-daemon/aws-xray-daemon-linux-3.x.zip -o aws-xray-daemon-linux-3.x.zip + unzip aws-xray-daemon-linux-3.x.zip -d aws-xray-daemon-linux-3.x + chmod +x ./aws-xray-daemon-linux-3.x/xray + ./aws-xray-daemon-linux-3.x/xray -o -n "$region" & -enable_cloudwatch_agent=$(echo "$parameters" | jq --arg environment "$environment" -r '.[] | select(.Name == "/\($environment)/runner/enable-cloudwatch") | .Value') -echo "Retrieved /$environment/runner/enable-cloudwatch parameter - ($enable_cloudwatch_agent)" -agent_mode=$(echo "$parameters" | jq --arg environment "$environment" -r '.[] | select(.Name == "/\($environment)/runner/agent-mode") | .Value') -echo "Retrieved /$environment/runner/agent-mode parameter - ($agent_mode)" + SEGMENT=$(create_xray_start_segment "$xray_trace_id" "$instance_id") + echo "$SEGMENT" +fi if [[ "$enable_cloudwatch_agent" == "true" ]]; then echo "Cloudwatch is enabled" - amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c "ssm:$environment-cloudwatch_agent_config_runner" + amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c "ssm:$ssm_config_path/cloudwatch_agent_config_runner" fi ## Configure the runner echo "Get GH Runner config from AWS SSM" -config=$(aws ssm get-parameters --names "$environment"-"$instance_id" --with-decryption --region "$region" | jq -r ".Parameters | .[0] | .Value") - +config=$(aws ssm get-parameter --name "$token_path"/"$instance_id" --with-decryption --region "$region" | jq -r ".Parameter | .Value") while [[ -z "$config" ]]; do echo "Waiting for GH Runner config to become available in AWS SSM" sleep 1 - config=$(aws ssm get-parameters --names "$environment"-"$instance_id" --with-decryption --region "$region" | jq -r ".Parameters | .[0] | .Value") + config=$(aws ssm get-parameter --name "$token_path"/"$instance_id" --with-decryption --region "$region" | jq -r ".Parameter | .Value") done echo "Delete GH Runner token from AWS SSM" -aws ssm delete-parameter --name "$environment"-"$instance_id" --region "$region" +aws ssm delete-parameter --name "$token_path"/"$instance_id" --region "$region" if [ -z "$run_as" ]; then echo "No user specified, using default ec2-user account" @@ -59,11 +189,8 @@ fi chown -R $run_as . -echo "Configure GH Runner as user $run_as" -sudo --preserve-env=RUNNER_ALLOW_RUNASROOT -u "$run_as" -- ./config.sh --unattended --name "$instance_id" --work "_work" $${config} - info_arch=$(uname -p) -info_os=$(( lsb_release -ds || cat /etc/*release || uname -om ) 2>/dev/null | head -n1 | cut -d "=" -f2- | tr -d '"') +info_os=$( ( lsb_release -ds || cat /etc/*release || uname -om ) 2>/dev/null | head -n1 | cut -d "=" -f2- | tr -d '"') tee /opt/actions-runner/.setup_info </opt/start-runner-service.sh <<-EOF +create_xray_success_segment "$SEGMENT" +if [[ $agent_mode = "ephemeral" ]]; then echo "Starting the runner in ephemeral mode" - sudo --preserve-env=RUNNER_ALLOW_RUNASROOT -u "$run_as" -- ./run.sh - echo "Runner has finished" - - echo "Stopping cloudwatch service" - systemctl stop amazon-cloudwatch-agent.service - echo "Terminating instance" - aws ec2 terminate-instances --instance-ids "$instance_id" --region "$region" -EOF - chmod 755 /opt/start-runner-service.sh - # Starting the runner via a own process to ensure this process terminates - nohup /opt/start-runner-service.sh & + if [[ "$enable_jit_config" == "true" ]]; then + echo "Starting with JIT config" + sudo --preserve-env=RUNNER_ALLOW_RUNASROOT -u "$run_as" -- ./run.sh --jitconfig $${config} + else + echo "Starting without JIT config" + sudo --preserve-env=RUNNER_ALLOW_RUNASROOT -u "$run_as" -- ./run.sh + fi + echo "Runner has finished" else echo "Installing the runner as a service" ./svc.sh install "$run_as" diff --git a/modules/runners/templates/user-data.sh b/modules/runners/templates/user-data.sh index 08465eba97..68edb79b0a 100644 --- a/modules/runners/templates/user-data.sh +++ b/modules/runners/templates/user-data.sh @@ -1,5 +1,22 @@ #!/bin/bash -e +install_with_retry() { + max_attempts=5 + attempt_count=0 + success=false + while [ $success = false ] && [ $attempt_count -le $max_attempts ]; do + echo "Attempting $attempt_count/$max_attempts: Installing $*" + dnf install -y $* + if [ $? -eq 0 ]; then + success=true + else + echo "Failed to install $1 - retrying" + attempt_count=$(( attempt_count + 1 )) + sleep 5 + fi + done +} + exec > >(tee /var/log/user-data.log | logger -t user-data -s 2>/dev/console) 2>&1 # AWS suggest to create a log for debug purpose based on https://aws.amazon.com/premiumsupport/knowledge-center/ec2-linux-log-user-data/ @@ -15,14 +32,29 @@ set -x ${pre_install} -yum update -y +max_attempts=5 +attempt_count=0 +success=false +while [ $success = false ] && [ $attempt_count -le $max_attempts ]; do + echo "Attempting $attempt_count/$max_attempts: upgrade-minimal" + dnf upgrade-minimal -y +if [ $? -eq 0 ]; then + success=true + else + echo "Failed to run `dnf upgrad-minimal -y` - retrying" + attempt_count=$(( attempt_count + 1 )) + sleep 5 + fi +done # Install docker -amazon-linux-extras install docker +install_with_retry docker + service docker start usermod -a -G docker ec2-user -yum install -y amazon-cloudwatch-agent curl jq git +install_with_retry amazon-cloudwatch-agent jq git +install_with_retry --allowerasing curl user_name=ec2-user diff --git a/modules/runners/variables.tf b/modules/runners/variables.tf index fe3e521d41..d8683088cd 100644 --- a/modules/runners/variables.tf +++ b/modules/runners/variables.tf @@ -29,17 +29,6 @@ variable "tags" { default = {} } -variable "environment" { - description = "A name that identifies the environment, used as prefix and for tagging." - type = string - default = null - - validation { - condition = var.environment == null - error_message = "The \"environment\" variable is no longer used. To migrate, set the \"prefix\" variable to the original value of \"environment\" and optionally, add \"Environment\" to the \"tags\" variable map with the same value." - } -} - variable "prefix" { description = "The prefix used for naming resources" type = string @@ -58,38 +47,25 @@ variable "s3_runner_binaries" { variable "block_device_mappings" { description = "The EC2 instance block device configuration. Takes the following keys: `device_name`, `delete_on_termination`, `volume_type`, `volume_size`, `encrypted`, `iops`, `throughput`, `kms_key_id`, `snapshot_id`." type = list(object({ - delete_on_termination = bool - device_name = string - encrypted = bool - iops = number - kms_key_id = string - snapshot_id = string - throughput = number + delete_on_termination = optional(bool, true) + device_name = optional(string, "/dev/xvda") + encrypted = optional(bool, true) + iops = optional(number) + kms_key_id = optional(string) + snapshot_id = optional(string) + throughput = optional(number) volume_size = number - volume_type = string + volume_type = optional(string, "gp3") })) default = [{ - delete_on_termination = true - device_name = "/dev/xvda" - encrypted = true - iops = null - kms_key_id = null - snapshot_id = null - throughput = null - volume_size = 30 - volume_type = "gp3" + volume_size = 30 }] } -variable "market_options" { - description = "DEPCRECATED: Replaced by `instance_target_capacity_type`." - type = string - default = null - - validation { - condition = anytrue([var.market_options == null]) - error_message = "Deprecated, replaced by `instance_target_capacity_type`." - } +variable "ebs_optimized" { + description = "The EC2 EBS optimized configuration." + type = bool + default = false } variable "instance_target_capacity_type" { @@ -131,14 +107,8 @@ variable "runner_os" { } } -variable "instance_type" { - description = "[DEPRECATED] See instance_types." - type = string - default = "m5.large" -} - variable "instance_types" { - description = "List of instance types for the action runner. Defaults are based on runner_os (amzn2 for linux and Windows Server Core for win)." + description = "List of instance types for the action runner. Defaults are based on runner_os (al2023 for linux and Windows Server Core for win)." type = list(string) default = null } @@ -146,7 +116,12 @@ variable "instance_types" { variable "ami_filter" { description = "Map of lists used to create the AMI filter for the action runner AMI." type = map(list(string)) - default = null + default = { state = ["available"] } + validation { + # check the availability of the AMI + condition = contains(keys(var.ami_filter), "state") + error_message = "The \"ami_filter\" variable must contain the \"state\" key with the value \"available\"." + } } variable "ami_owners" { @@ -161,14 +136,26 @@ variable "ami_id_ssm_parameter_name" { default = null } -variable "enabled_userdata" { +variable "ami_kms_key_arn" { + description = "Optional CMK Key ARN to be used to launch an instance from a shared encrypted AMI" + type = string + default = null +} + +variable "enable_userdata" { description = "Should the userdata script be enabled for the runner. Set this to false if you are using your own prebuilt AMI" type = bool default = true } variable "userdata_template" { - description = "Alternative user-data template, replacing the default template. By providing your own user_data you have to take care of installing all required software, including the action runner. Variables userdata_pre/post_install are ignored." + description = "Alternative user-data template file path, replacing the default template. By providing your own user_data you have to take care of installing all required software, including the action runner. Variables userdata_pre/post_install are ignored." + type = string + default = null +} + +variable "userdata_content" { + description = "Alternative user-data content, replacing the templated one. By providing your own user_data you have to take care of installing all required software, including the action runner and registering the runner. Be-aware configuration paramaters in SSM as well as tags are treated as internals. Changes will not trigger a breaking release." type = string default = null } @@ -193,7 +180,8 @@ variable "sqs_build_queue" { } variable "enable_organization_runners" { - type = bool + description = "Register runners to organization, instead of repo level" + type = bool } variable "github_app_parameters" { @@ -204,6 +192,12 @@ variable "github_app_parameters" { }) } +variable "lambda_scale_down_memory_size" { + description = "Memory size limit in MB for scale down lambda." + type = number + default = 512 +} + variable "scale_down_schedule_expression" { description = "Scheduler expression to check every x for scale down." type = string @@ -222,10 +216,9 @@ variable "runner_boot_time_in_minutes" { default = 5 } -variable "runner_extra_labels" { - description = "Extra labels for the runners (GitHub). Separate each label by a comma" - type = string - default = "" +variable "runner_labels" { + description = "All the labels for the runners (GitHub) including the default one's(e.g: self-hosted, linux, x64, label1, label2). Separate each label by a comma" + type = list(string) } variable "runner_group_name" { @@ -252,6 +245,12 @@ variable "scale_up_reserved_concurrent_executions" { default = 1 } +variable "lambda_scale_up_memory_size" { + description = "Memory size limit in MB for scale-up lambda." + type = number + default = 512 +} + variable "lambda_timeout_scale_up" { description = "Time out for the scale up lambda in seconds." type = number @@ -289,7 +288,7 @@ variable "runner_run_as" { } variable "runners_maximum_count" { - description = "The maximum number of runners that will be created." + description = "The maximum number of runners that will be created. Setting the variable to `-1` desiables the maximum check." type = number default = 3 } @@ -303,9 +302,10 @@ variable "runner_architecture" { variable "idle_config" { description = "List of time period that can be defined as cron expression to keep a minimum amount of runners active instead of scaling down to 0. By defining this list you can ensure that in time periods that match the cron expression within 5 seconds a runner is kept idle." type = list(object({ - cron = string - timeZone = string - idleCount = number + cron = string + timeZone = string + idleCount = number + evictionStrategy = optional(string, "oldest_first") })) default = [] } @@ -329,16 +329,19 @@ variable "enable_ssm_on_runners" { variable "lambda_s3_bucket" { description = "S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly." + type = string default = null } variable "runners_lambda_s3_key" { description = "S3 key for runners lambda function. Required if using S3 bucket to specify lambdas." + type = string default = null } variable "runners_lambda_s3_object_version" { description = "S3 object version for runners lambda function. Useful if S3 versioning is enabled on source bucket." + type = string default = null } @@ -463,20 +466,6 @@ variable "egress_rules" { }] } -variable "log_type" { - description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " - type = string - default = "pretty" - validation { - condition = anytrue([ - var.log_type == "json", - var.log_type == "pretty", - var.log_type == "hidden", - ]) - error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." - } -} - variable "log_level" { description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." type = string @@ -507,7 +496,7 @@ variable "metadata_options" { default = { instance_metadata_tags = "enabled" http_endpoint = "enabled" - http_tokens = "optional" + http_tokens = "required" http_put_response_hop_limit = 1 } } @@ -530,6 +519,12 @@ variable "pool_lambda_timeout" { default = 60 } +variable "pool_lambda_memory_size" { + description = "Lambda Memory size limit in MB for pool lambda" + type = number + default = 512 +} + variable "pool_runner_owner" { description = "The pool will deploy runners to the GitHub org ID, set this value to the org to which you want the runners deployed. Repo level is not supported." type = string @@ -552,7 +547,7 @@ variable "pool_config" { } variable "disable_runner_autoupdate" { - description = "Disable the auto update of the github runner agent. Be-aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/)" + description = "Disable the auto update of the github runner agent. Be aware there is a grace period of 30 days, see also the [GitHub article](https://github.blog/changelog/2022-02-01-github-actions-self-hosted-runners-can-now-disable-automatic-updates/)" type = bool default = false } @@ -560,13 +555,13 @@ variable "disable_runner_autoupdate" { variable "lambda_runtime" { description = "AWS Lambda runtime." type = string - default = "nodejs16.x" + default = "nodejs20.x" } variable "lambda_architecture" { description = "AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86_64' functions. " type = string - default = "x86_64" + default = "arm64" validation { condition = contains(["arm64", "x86_64"], var.lambda_architecture) error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." @@ -583,3 +578,92 @@ variable "enable_user_data_debug_logging" { type = bool default = false } + +variable "ssm_paths" { + description = "The root path used in SSM to store configuration and secrets." + type = object({ + root = string + tokens = string + config = string + }) +} + +variable "runner_name_prefix" { + description = "The prefix used for the GitHub runner name. The prefix will be used in the default start script to prefix the instance name when register the runner in GitHub. The value is availabe via an EC2 tag 'ghr:runner_name_prefix'." + type = string + default = "" + validation { + condition = length(var.runner_name_prefix) <= 45 + error_message = "The prefix used for the GitHub runner name must be less than 32 characters. AWS instances id are 17 chars, https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/resource-ids.html" + } +} + +variable "tracing_config" { + description = "Configuration for lambda tracing." + type = object({ + mode = optional(string, null) + capture_http_requests = optional(bool, false) + capture_error = optional(bool, false) + }) + default = {} +} + + +variable "credit_specification" { + description = "The credit option for CPU usage of a T instance. Can be unset, \"standard\" or \"unlimited\"." + type = string + default = null + + validation { + condition = var.credit_specification == null ? true : contains(["standard", "unlimited"], var.credit_specification) + error_message = "Valid values for credit_specification are (null, \"standard\", \"unlimited\")." + } +} + +variable "enable_jit_config" { + description = "Overwrite the default behavior for JIT configuration. By default JIT configuration is enabled for ephemeral runners and disabled for non-ephemeral runners. In case of GHES check first if the JIT config API is avaialbe. In case you upgradeing from 3.x to 4.x you can set `enable_jit_config` to `false` to avoid a breaking change when having your own AMI." + type = bool + default = null +} + +variable "associate_public_ipv4_address" { + description = "Associate public IPv4 with the runner. Only tested with IPv4" + type = bool + default = false +} + +variable "ssm_housekeeper" { + description = < + + ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.14.1 | -| [aws](#requirement\_aws) | ~> 4.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | ~> 4.0 | +| [aws](#provider\_aws) | ~> 5.27 | ## Modules @@ -70,7 +71,6 @@ No modules. |------|-------------|------|---------|:--------:| | [account\_id](#input\_account\_id) | The module allows to switch to the created role from the provided account id. | `string` | n/a | yes | | [aws\_partition](#input\_aws\_partition) | (optional) partition in the arn namespace if not aws | `string` | `"aws"` | no | -| [environment](#input\_environment) | A name that identifies the environment, used as prefix and for tagging. | `string` | `null` | no | | [namespaces](#input\_namespaces) | The role will be only allowed to create roles, policies and instance profiles in the given namespace / path. All policies in the boundaries namespace cannot be modified by this role. |
object({
boundary_namespace = string
role_namespace = string
policy_namespace = string
instance_profile_namespace = string
})
| n/a | yes | | [prefix](#input\_prefix) | The prefix used for naming resources | `string` | `"github-actions"` | no | @@ -80,7 +80,7 @@ No modules. |------|-------------| | [boundary](#output\_boundary) | n/a | | [role](#output\_role) | n/a | - + ## Philips Forest diff --git a/modules/setup-iam-permissions/policies/boundary.json b/modules/setup-iam-permissions/policies/boundary.json index 5e9363456a..bed7d6a334 100644 --- a/modules/setup-iam-permissions/policies/boundary.json +++ b/modules/setup-iam-permissions/policies/boundary.json @@ -13,7 +13,8 @@ "resource-groups:*", "ssm:*", "ssmmessages:*", - "ec2messages:*" + "ec2messages:*", + "cloudwatch:*" ], "Resource": "*" }, diff --git a/modules/setup-iam-permissions/policies/deploy-boundary.json b/modules/setup-iam-permissions/policies/deploy-boundary.json index e6111e5f19..bb93622e8a 100644 --- a/modules/setup-iam-permissions/policies/deploy-boundary.json +++ b/modules/setup-iam-permissions/policies/deploy-boundary.json @@ -52,7 +52,8 @@ "iam:RemoveRoleFromInstanceProfile", "iam:DeleteInstanceProfile", "iam:AddRoleToInstanceProfile", - "iam:GetInstanceProfile" + "iam:GetInstanceProfile", + "iam:TagInstanceProfile" ], "Resource": "arn:${aws_partition}:iam::${account_id}:instance-profile/${instance_profile_namespace}/*" }, diff --git a/modules/setup-iam-permissions/variables.tf b/modules/setup-iam-permissions/variables.tf index 833ee873f5..cc7fc3d936 100644 --- a/modules/setup-iam-permissions/variables.tf +++ b/modules/setup-iam-permissions/variables.tf @@ -1,14 +1,3 @@ -variable "environment" { - description = "A name that identifies the environment, used as prefix and for tagging." - type = string - default = null - - validation { - condition = var.environment == null - error_message = "The \"environment\" variable is no longer used. To migrate, set the \"prefix\" variable to the original value of \"environment\" and optionally, add \"Environment\" to the \"tags\" variable map with the same value." - } -} - variable "prefix" { description = "The prefix used for naming resources" type = string diff --git a/modules/setup-iam-permissions/versions.tf b/modules/setup-iam-permissions/versions.tf index ac1bb9a5d5..1df1926c45 100644 --- a/modules/setup-iam-permissions/versions.tf +++ b/modules/setup-iam-permissions/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.14.1" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } } } diff --git a/modules/ssm/README.md b/modules/ssm/README.md new file mode 100644 index 0000000000..f09b5c1182 --- /dev/null +++ b/modules/ssm/README.md @@ -0,0 +1,47 @@ +# Module - AWS System Manager Parameter store + +> This module is treated as internal module, breaking changes will not trigger a major release bump. + +This module is used for storing configuration of runners, registration tokens and secrets for the Lambda's in AWS System Manager Parameter store. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.27 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_ssm_parameter.github_app_id](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.github_app_key_base64](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.github_app_webhook_secret](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [github\_app](#input\_github\_app) | GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
webhook_secret = string
})
| n/a | yes | +| [kms\_key\_arn](#input\_kms\_key\_arn) | Optional CMK Key ARN to be used for Parameter Store. | `string` | `null` | no | +| [path\_prefix](#input\_path\_prefix) | The path prefix used for naming resources | `string` | n/a | yes | +| [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [parameters](#output\_parameters) | n/a | + diff --git a/modules/ssm/ssm.tf b/modules/ssm/ssm.tf index 9b4d96cb1f..6bf3291e37 100644 --- a/modules/ssm/ssm.tf +++ b/modules/ssm/ssm.tf @@ -1,5 +1,5 @@ resource "aws_ssm_parameter" "github_app_id" { - name = "/actions_runner/${var.prefix}/github_app_id" + name = "${var.path_prefix}/github_app_id" type = "SecureString" value = var.github_app.id key_id = local.kms_key_arn @@ -7,7 +7,7 @@ resource "aws_ssm_parameter" "github_app_id" { } resource "aws_ssm_parameter" "github_app_key_base64" { - name = "/actions_runner/${var.prefix}/github_app_key_base64" + name = "${var.path_prefix}/github_app_key_base64" type = "SecureString" value = var.github_app.key_base64 key_id = local.kms_key_arn @@ -15,7 +15,7 @@ resource "aws_ssm_parameter" "github_app_key_base64" { } resource "aws_ssm_parameter" "github_app_webhook_secret" { - name = "/actions_runner/${var.prefix}/github_app_webhook_secret" + name = "${var.path_prefix}/github_app_webhook_secret" type = "SecureString" value = var.github_app.webhook_secret key_id = local.kms_key_arn diff --git a/modules/ssm/variables.tf b/modules/ssm/variables.tf index 4078ad6d1c..310f3a8d89 100644 --- a/modules/ssm/variables.tf +++ b/modules/ssm/variables.tf @@ -7,21 +7,9 @@ variable "github_app" { }) } -variable "environment" { - description = "A name that identifies the environment, used as prefix and for tagging." +variable "path_prefix" { + description = "The path prefix used for naming resources" type = string - default = null - - validation { - condition = var.environment == null - error_message = "The \"environment\" variable is no longer used. To migrate, set the \"prefix\" variable to the original value of \"environment\" and optionally, add \"Environment\" to the \"tags\" variable map with the same value." - } -} - -variable "prefix" { - description = "The prefix used for naming resources" - type = string - default = "github-actions" } variable "kms_key_arn" { diff --git a/modules/ssm/versions.tf b/modules/ssm/versions.tf index ac1bb9a5d5..1df1926c45 100644 --- a/modules/ssm/versions.tf +++ b/modules/ssm/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.14.1" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" } } } diff --git a/modules/termination-watcher/README.md b/modules/termination-watcher/README.md new file mode 100644 index 0000000000..fc6326b003 --- /dev/null +++ b/modules/termination-watcher/README.md @@ -0,0 +1,98 @@ +# Module - Termination Watcher + +This module is watching spot termination events published by the Event Bridge. A lambda function will look up the instance details and create a log line for the notification warning. Optionally a metric will be created. + +## Usages + +The module is part of the root and multi-runner module but can also be used stand-alone. Below a direction for configuration. + +``` +module "termination_watcher" { + source = "path to module" + + config = { + prefix = "global" + tag_filters = { + "ghr:Applicaton" = "github-action-runner" + } + metrics_namespace = "My Metrics + s3_bucket = "..." + s3_key = "..." + s3_object_version = "..." + + enable_metric = { + spot_warning = true + })) + } +} + +``` + +## Development + +The Lambda function is written in [TypeScript](https://www.typescriptlang.org/) and requires Node and yarn. Sources are located in [https://github.com/philips-labs/terraform-aws-github-runner/tree/main/lambdas]. + +### Install + +```bash +cd lambdas +yarn install +``` + +### Test + +Test are implemented with [Jest](https://jestjs.io/), calls to AWS and GitHub are mocked. + +```bash +yarn run test +``` + +### Package + +To compile all TypeScript/JavaScript sources in a single file [ncc](https://github.com/zeit/ncc) is used. + +```bash +yarn run dist +``` + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.27 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [termination\_warning\_watcher](#module\_termination\_warning\_watcher) | ../lambda | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_cloudwatch_event_rule.spot_instance_termination_warning](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | +| [aws_cloudwatch_event_target.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | +| [aws_iam_role_policy.lambda_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_lambda_permission.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [config](#input\_config) | Configuration for the spot termination watcher lambda function.

`aws_partition`: Partition for the base arn if not 'aws'
`architecture`: AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions.
`environment_variables`: Environment variables for the lambda.
`enable_metric`: Enable metric for the lambda. If `spot_warning` is set to true, the lambda will emit a metric when it detects a spot termination warning.
`lambda_principals`: Add extra principals to the role created for execution of the lambda, e.g. for local testing.
`lambda_tags`: Map of tags that will be added to created resources. By default resources will be tagged with name and environment.
`log_level`: Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'.
`logging_kms_key_id`: Specifies the kms key id to encrypt the logs with
`logging_retention_in_days`: Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653.
`memory_size`: Memory size linit in MB of the lambda.
`metrics_namespace`: Namespace for the metrics emitted by the lambda.
`prefix`: The prefix used for naming resources.
`role_path`: The path that will be added to the role, if not set the environment name will be used.
`role_permissions_boundary`: Permissions boundary that will be added to the created role for the lambda.
`runtime`: AWS Lambda runtime.
`s3_bucket`: S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly.
`s3_key`: S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas.
`s3_object_version`: S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket.
`security_group_ids`: List of security group IDs associated with the Lambda function.
`subnet_ids`: List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`.
`tag_filters`: Map of tags that will be used to filter the resources to be tracked. Only for which all tags are present and starting with the same value as the value in the map will be tracked.
`tags`: Map of tags that will be added to created resources. By default resources will be tagged with name and environment.
`timeout`: Time out of the lambda in seconds.
`tracing_config`: Configuration for lambda tracing.
`zip`: File location of the lambda zip file. |
object({
aws_partition = optional(string, null)
architecture = optional(string, null)
enable_metric = optional(object({
spot_warning = optional(bool, false)
}))
environment_variables = optional(map(string), {})
lambda_tags = optional(map(string), {})
log_level = optional(string, null)
logging_kms_key_id = optional(string, null)
logging_retention_in_days = optional(number, null)
memory_size = optional(number, null)
metrics_namespace = optional(string, null)
prefix = optional(string, null)
principals = optional(list(object({
type = string
identifiers = list(string)
})), [])
role_path = optional(string, null)
role_permissions_boundary = optional(string, null)
runtime = optional(string, null)
s3_bucket = optional(string, null)
s3_key = optional(string, null)
s3_object_version = optional(string, null)
security_group_ids = optional(list(string), [])
subnet_ids = optional(list(string), [])
tag_filters = optional(map(string), null)
tags = optional(map(string), {})
timeout = optional(number, null)
tracing_config = optional(object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
}), {})
zip = optional(string, null)
})
| n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [lambda](#output\_lambda) | n/a | + diff --git a/modules/termination-watcher/main.tf b/modules/termination-watcher/main.tf new file mode 100644 index 0000000000..48e03fd6e3 --- /dev/null +++ b/modules/termination-watcher/main.tf @@ -0,0 +1,49 @@ +locals { + lambda_zip = var.config.zip == null ? "${path.module}/../../lambdas/functions/termination-watcher/termination-watcher.zip" : var.config.zip + name = "spot-termination-watcher" + + environment_variables = { + ENABLE_METRICS_SPOT_WARNING = var.config.enable_metric != null ? var.config.enable_metric.spot_warning : false + TAG_FILTERS = jsonencode(var.config.tag_filters) + } + + config = merge(var.config, { name = local.name, handler = "index.interruptionWarning", zip = local.lambda_zip, environment_variables = local.environment_variables }) +} + +module "termination_warning_watcher" { + source = "../lambda" + lambda = local.config +} + + +resource "aws_cloudwatch_event_rule" "spot_instance_termination_warning" { + name = "${var.config.prefix != null ? format("%s-", var.config.prefix) : ""}spot-instance-termination" + description = "Spot Instance Termination Warning" + + event_pattern = < This module is treated as internal module, breaking changes will not trigger a major release bump. + +> This module is using the local executor to run a bash script. + +This module updates the GitHub App webhook with the endpoint and secret and can be changed with the root module. The module is used to update the webhook after applying the examples. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [null](#requirement\_null) | ~> 3 | + +## Providers + +| Name | Version | +|------|---------| +| [null](#provider\_null) | ~> 3 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [null_resource.update_app](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [github\_app](#input\_github\_app) | GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
webhook_secret = string
})
| n/a | yes | +| [webhook\_endpoint](#input\_webhook\_endpoint) | The endpoint to use for the webhook, defaults to the endpoint of the runners module. | `string` | n/a | yes | + +## Outputs + +No outputs. + diff --git a/modules/webhook-github-app/bin/update-app.sh b/modules/webhook-github-app/bin/update-app.sh new file mode 100755 index 0000000000..d9d468b20b --- /dev/null +++ b/modules/webhook-github-app/bin/update-app.sh @@ -0,0 +1,95 @@ +#!/bin/bash +set -e + +### CHECKS ### + +function testCommand() { + if ! command -v $1 &> /dev/null + then + echo "$1 could not be found" + exit + fi +} + +testCommand gh + +# create usages function usages mesaages. APP_ID and APP_PRIVATE_KEY_PATH are required as parameter or environment variable +usages() { + echo "Description: Update the GitHub App webhook configuration with terraform output for the webhook output of the module." >&2 + echo " " >&2 + echo "Usage: $0" >&2 + echo "Usage: $0 [-h]" >&2 + echo " Use environment variables" >&2 + echo " -a APP_ID GitHub App ID" >&2 + echo " -k APP_PRIVATE_KEY_BASE64 Base64 encoded private key of the GitHub App" >&2 + echo " -f APP APP_PRIVATE_KEY_FILE Path to the private key of the GitHub App" >&2 + echo " -e WEBHOOK_ENDPOINT Webhook endpoint" >&2 + echo " -s WEBHOOK_SECRET Webhook secret" >&2 + echo " -h Show this help message" >&2 + exit 1 +} + +# hadd h flag to show help +while getopts a:f:k:s:e:h flag +do + case "${flag}" in + a) APP_ID=${OPTARG};; + f) APP_PRIVATE_KEY_FILE=${OPTARG};; + k) APP_PRIVATE_KEY_BASE64=${OPTARG};; + e) WEBHOOK_ENDPOINT=${OPTARG};; + s) WEBHOOK_SECRET=${OPTARG};; + h) usages ;; + esac +done + +if [ -z "$APP_ID" ]; then + echo "APP_ID must be set" + usages +fi + +# check one of variables APP_PRIVATE_KEY_PATH or APP_PRIVATE_KEY are set +if [ -z "$APP_PRIVATE_KEY_BASE64" ] && [ -z "$APP_PRIVATE_KEY_FILE" ]; then + echo "APP_PRIVATE_KEY_BASE64 or APP_PRIVATE_KEY_FILE must be set" + usages +fi + +### Terraform outputs ### + +if [ -z "$WEBHOOK_ENDPOINT" ]; then + testCommand terraform + WEBHOOK_ENDPOINT=$(terraform output --raw webhook_endpoint) +fi + +if [ -z "$WEBHOOK_SECRET" ]; then + testCommand terraform + WEBHOOK_SECRET=$(terraform output --raw webhook_secret) +fi + +### CREATE JWT TOKEN ### + +# Generate the JWT header and payload +HEADER=$(echo -n '{"alg":"RS256","typ":"JWT"}' | base64 | tr -d '\n') +PAYLOAD=$(echo -n "{\"iat\":$(date +%s),\"exp\":$(( $(date +%s) + 600 )),\"iss\":$APP_ID}" | base64 | tr -d '\n') + +# Generate the signature +if [ -z "$APP_PRIVATE_KEY_BASE64" ]; then + APP_PRIVATE_KEY_BASE64=$(cat $APP_PRIVATE_KEY_FILE | base64 | tr -d '\n') +fi + +SIGNATURE=$(echo -n "$HEADER.$PAYLOAD" | openssl dgst -sha256 -sign <(echo -e "$APP_PRIVATE_KEY_BASE64" | base64 -d) | base64 | tr -d '\n') + +JWT_TOKEN="$HEADER.$PAYLOAD.$SIGNATURE" + + +### UPDATE WEBHOOK ### + +gh api \ + --method PATCH \ + -H "Authorization: Bearer ${JWT_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + /app/hook/config \ + -f content_type='json' \ + -f insecure_ssl='0' \ + -f secret=${WEBHOOK_SECRET} \ + -f url=${WEBHOOK_ENDPOINT} diff --git a/modules/webhook-github-app/main.tf b/modules/webhook-github-app/main.tf new file mode 100644 index 0000000000..609eb85279 --- /dev/null +++ b/modules/webhook-github-app/main.tf @@ -0,0 +1,12 @@ +resource "null_resource" "update_app" { + triggers = { + webhook_endpoint = var.webhook_endpoint + webhook_secret = var.github_app.webhook_secret + } + + provisioner "local-exec" { + interpreter = ["bash", "-c"] + command = "${path.module}/bin/update-app.sh -e ${var.webhook_endpoint} -s ${var.github_app.webhook_secret} -a ${var.github_app.id} -k ${var.github_app.key_base64}" + on_failure = continue + } +} diff --git a/modules/webhook-github-app/variables.tf b/modules/webhook-github-app/variables.tf new file mode 100644 index 0000000000..69d404b7b4 --- /dev/null +++ b/modules/webhook-github-app/variables.tf @@ -0,0 +1,13 @@ +variable "github_app" { + description = "GitHub app parameters, see your github app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`)." + type = object({ + key_base64 = string + id = string + webhook_secret = string + }) +} + +variable "webhook_endpoint" { + description = "The endpoint to use for the webhook, defaults to the endpoint of the runners module." + type = string +} diff --git a/modules/webhook-github-app/versions.tf b/modules/webhook-github-app/versions.tf new file mode 100644 index 0000000000..e0632ba7df --- /dev/null +++ b/modules/webhook-github-app/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.3.0" + + required_providers { + null = { + source = "hashicorp/null" + version = "~> 3" + } + } +} diff --git a/modules/webhook/README.md b/modules/webhook/README.md index 56896a2744..54aab121e0 100644 --- a/modules/webhook/README.md +++ b/modules/webhook/README.md @@ -1,10 +1,8 @@ # Module - GitHub App web hook -This module creates an API gateway endpoint and lambda function to handle GitHub App webhook events. - -## Usages +> This module is treated as internal module, breaking changes will not trigger a major release bump. -Usage examples are available in the root module. By default the root module will assume local zip files containing the lambda distribution are available. See the [download lambda module](../download-lambda/README.md) for more information. +This module creates an API gateway endpoint and lambda function to handle GitHub App webhook events. ## Lambda Function @@ -32,20 +30,21 @@ To compile all TypeScript/JavaScript sources in a single file [ncc](https://gith ```bash yarn run dist ``` - - + ## Requirements | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.14.1 | -| [aws](#requirement\_aws) | ~> 4.0 | +| [terraform](#requirement\_terraform) | >= 1.3.0 | +| [aws](#requirement\_aws) | ~> 5.27 | +| [null](#requirement\_null) | ~> 3.2 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | ~> 4.0 | +| [aws](#provider\_aws) | ~> 5.27 | +| [null](#provider\_null) | ~> 3.2 | ## Modules @@ -64,41 +63,48 @@ No modules. | [aws_iam_role_policy.webhook_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.webhook_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.webhook_ssm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.webhook_workflow_job_sqs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.webhook_vpc_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_lambda_function.webhook](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | | [aws_lambda_permission.webhook](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_ssm_parameter.runner_matcher_config](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ssm_parameter) | resource | +| [null_resource.github_app_parameters](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | | [aws_iam_policy_document.lambda_assume_role_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_xray](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [aws\_region](#input\_aws\_region) | AWS region. | `string` | n/a | yes | -| [disable\_check\_wokflow\_job\_labels](#input\_disable\_check\_wokflow\_job\_labels) | Disable the check of workflow labels. | `bool` | `false` | no | -| [enable\_workflow\_job\_labels\_check](#input\_enable\_workflow\_job\_labels\_check) | If set to true all labels in the workflow job even are matched against the custom labels and GitHub labels (os, architecture and `self-hosted`). When the labels are not matching the event is dropped at the webhook. | `bool` | `false` | no | -| [environment](#input\_environment) | A name that identifies the environment, used as prefix and for tagging. | `string` | `null` | no | -| [github\_app\_webhook\_secret\_arn](#input\_github\_app\_webhook\_secret\_arn) | n/a | `string` | n/a | yes | +| [aws\_partition](#input\_aws\_partition) | (optional) partition for the base arn if not 'aws' | `string` | `"aws"` | no | +| [github\_app\_parameters](#input\_github\_app\_parameters) | Parameter Store for GitHub App Parameters. |
object({
webhook_secret = map(string)
})
| n/a | yes | | [kms\_key\_arn](#input\_kms\_key\_arn) | Optional CMK Key ARN to be used for Parameter Store. | `string` | `null` | no | -| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"x86_64"` | no | -| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs16.x"` | no | -| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `any` | `null` | no | +| [lambda\_architecture](#input\_lambda\_architecture) | AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86\_64' functions. | `string` | `"arm64"` | no | +| [lambda\_memory\_size](#input\_lambda\_memory\_size) | Memory size limit in MB for lambda. | `number` | `256` | no | +| [lambda\_runtime](#input\_lambda\_runtime) | AWS Lambda runtime. | `string` | `"nodejs20.x"` | no | +| [lambda\_s3\_bucket](#input\_lambda\_s3\_bucket) | S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly. | `string` | `null` | no | +| [lambda\_security\_group\_ids](#input\_lambda\_security\_group\_ids) | List of security group IDs associated with the Lambda function. | `list(string)` | `[]` | no | +| [lambda\_subnet\_ids](#input\_lambda\_subnet\_ids) | List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`. | `list(string)` | `[]` | no | +| [lambda\_tags](#input\_lambda\_tags) | Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags. | `map(string)` | `{}` | no | | [lambda\_timeout](#input\_lambda\_timeout) | Time out of the lambda in seconds. | `number` | `10` | no | | [lambda\_zip](#input\_lambda\_zip) | File location of the lambda zip file. | `string` | `null` | no | | [log\_level](#input\_log\_level) | Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'. | `string` | `"info"` | no | -| [log\_type](#input\_log\_type) | Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. | `string` | `"pretty"` | no | | [logging\_kms\_key\_id](#input\_logging\_kms\_key\_id) | Specifies the kms key id to encrypt the logs with | `string` | `null` | no | -| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `7` | no | +| [logging\_retention\_in\_days](#input\_logging\_retention\_in\_days) | Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653. | `number` | `180` | no | +| [matcher\_config\_parameter\_store\_tier](#input\_matcher\_config\_parameter\_store\_tier) | The tier of the parameter store for the matcher configuration. Valid values are `Standard`, and `Advanced`. | `string` | `"Standard"` | no | | [prefix](#input\_prefix) | The prefix used for naming resources | `string` | `"github-actions"` | no | -| [repository\_white\_list](#input\_repository\_white\_list) | List of repositories allowed to use the github app | `list(string)` | `[]` | no | +| [repository\_white\_list](#input\_repository\_white\_list) | List of github repository full names (owner/repo\_name) that will be allowed to use the github app. Leave empty for no filtering. | `list(string)` | `[]` | no | | [role\_path](#input\_role\_path) | The path that will be added to the role; if not set, the environment name will be used. | `string` | `null` | no | | [role\_permissions\_boundary](#input\_role\_permissions\_boundary) | Permissions boundary that will be added to the created role for the lambda. | `string` | `null` | no | -| [runner\_labels](#input\_runner\_labels) | Extra (custom) labels for the runners (GitHub). Separate each label by a comma. Labels checks on the webhook can be enforced by setting `enable_workflow_job_labels_check`. GitHub read-only labels should not be provided. | `string` | `""` | no | -| [sqs\_build\_queue](#input\_sqs\_build\_queue) | SQS queue to publish accepted build events. |
object({
id = string
arn = string
})
| n/a | yes | -| [sqs\_build\_queue\_fifo](#input\_sqs\_build\_queue\_fifo) | Enable a FIFO queue to remain the order of events received by the webhook. Suggest to set to true for repo level runners. | `bool` | `false` | no | +| [runner\_matcher\_config](#input\_runner\_matcher\_config) | SQS queue to publish accepted build events based on the runner type. When exact match is disabled the webhook accepts the event if one of the workflow job labels is part of the matcher. The priority defines the order the matchers are applied. |
map(object({
arn = string
id = string
fifo = bool
matcherConfig = object({
labelMatchers = list(list(string))
exactMatch = bool
priority = optional(number, 999)
})
}))
| n/a | yes | +| [sqs\_workflow\_job\_queue](#input\_sqs\_workflow\_job\_queue) | SQS queue to monitor github events. |
object({
id = string
arn = string
})
| `null` | no | +| [ssm\_paths](#input\_ssm\_paths) | The root path used in SSM to store configuration and secrets. |
object({
root = string
webhook = string
})
| n/a | yes | | [tags](#input\_tags) | Map of tags that will be added to created resources. By default resources will be tagged with name and environment. | `map(string)` | `{}` | no | +| [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. |
object({
mode = optional(string, null)
capture_http_requests = optional(bool, false)
capture_error = optional(bool, false)
})
| `{}` | no | | [webhook\_lambda\_apigateway\_access\_log\_settings](#input\_webhook\_lambda\_apigateway\_access\_log\_settings) | Access log settings for webhook API gateway. |
object({
destination_arn = string
format = string
})
| `null` | no | -| [webhook\_lambda\_s3\_key](#input\_webhook\_lambda\_s3\_key) | S3 key for webhook lambda function. Required if using S3 bucket to specify lambdas. | `any` | `null` | no | -| [webhook\_lambda\_s3\_object\_version](#input\_webhook\_lambda\_s3\_object\_version) | S3 object version for webhook lambda function. Useful if S3 versioning is enabled on source bucket. | `any` | `null` | no | -| [workflow\_job\_labels\_check\_all](#input\_workflow\_job\_labels\_check\_all) | If set to true all labels in the workflow job must match the GitHub labels (os, architecture and `self-hosted`). When false if __any__ label matches it will trigger the webhook. `enable_workflow_job_labels_check` must be true for this to take effect. | `bool` | `true` | no | +| [webhook\_lambda\_s3\_key](#input\_webhook\_lambda\_s3\_key) | S3 key for webhook lambda function. Required if using S3 bucket to specify lambdas. | `string` | `null` | no | +| [webhook\_lambda\_s3\_object\_version](#input\_webhook\_lambda\_s3\_object\_version) | S3 object version for webhook lambda function. Useful if S3 versioning is enabled on source bucket. | `string` | `null` | no | ## Outputs @@ -107,23 +113,6 @@ No modules. | [endpoint\_relative\_path](#output\_endpoint\_relative\_path) | n/a | | [gateway](#output\_gateway) | n/a | | [lambda](#output\_lambda) | n/a | +| [lambda\_log\_group](#output\_lambda\_log\_group) | n/a | | [role](#output\_role) | n/a | - - -## Philips Forest - -This module is part of the Philips Forest. - -```plain - ___ _ - / __\__ _ __ ___ ___| |_ - / _\/ _ \| '__/ _ \/ __| __| - / / | (_) | | | __/\__ \ |_ - \/ \___/|_| \___||___/\__| - - Infrastructure -``` - -Talk to the forestkeepers in the `forest`-channel on Slack. - -[![Slack](https://philips-software-slackin.now.sh/badge.svg)](https://philips-software-slackin.now.sh) + diff --git a/modules/webhook/lambdas/webhook/.eslintrc.yaml b/modules/webhook/lambdas/webhook/.eslintrc.yaml deleted file mode 100644 index 682ae5cefa..0000000000 --- a/modules/webhook/lambdas/webhook/.eslintrc.yaml +++ /dev/null @@ -1,23 +0,0 @@ -env: - browser: true - es2021: true -extends: - #- google - - eslint:recommended - - plugin:@typescript-eslint/recommended -parser: "@typescript-eslint/parser" -parserOptions: - ecmaVersion: 12 - sourceType: module -plugins: - - "@typescript-eslint" -rules: - semi: error - max-len: - - error - - 120 - -overrides: - - files: - - "*.ts" - - "*.tsx" diff --git a/modules/webhook/lambdas/webhook/.gitignore b/modules/webhook/lambdas/webhook/.gitignore deleted file mode 100644 index 981918a850..0000000000 --- a/modules/webhook/lambdas/webhook/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# dependencies -node_modules/ - -# production -dist/ -build/ - -# misc -.DS_Store -.env* -*.zip - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/modules/webhook/lambdas/webhook/.nvmrc b/modules/webhook/lambdas/webhook/.nvmrc deleted file mode 100644 index 5edcff0364..0000000000 --- a/modules/webhook/lambdas/webhook/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v16 \ No newline at end of file diff --git a/modules/webhook/lambdas/webhook/.prettierrc b/modules/webhook/lambdas/webhook/.prettierrc deleted file mode 100644 index 3eb40208ef..0000000000 --- a/modules/webhook/lambdas/webhook/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "printWidth": 120, - "singleQuote": true, - "trailingComma": "all", - "semi": true, - "importOrderSeparation": true, - "importOrderSortSpecifiers": true, - "importOrder": [ - "", - "^[./]" - ] -} \ No newline at end of file diff --git a/modules/webhook/lambdas/webhook/jest.config.js b/modules/webhook/lambdas/webhook/jest.config.js deleted file mode 100644 index 02a6524ce9..0000000000 --- a/modules/webhook/lambdas/webhook/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', - collectCoverage: true, - collectCoverageFrom: ['src/**/*.{ts,js,jsx}', '!src/**/*local*.ts'], - coverageThreshold: { - global: { - branches: 85, - functions: 85, - lines: 85, - statements: 85 - } - } -}; diff --git a/modules/webhook/lambdas/webhook/package.json b/modules/webhook/lambdas/webhook/package.json deleted file mode 100644 index cb445f3253..0000000000 --- a/modules/webhook/lambdas/webhook/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "github-runner-lambda-agent-webhook", - "version": "1.0.0", - "main": "lambda.ts", - "license": "MIT", - "scripts": { - "start": "ts-node-dev src/local.ts", - "test": "NODE_ENV=test jest", - "test:watch": "NODE_ENV=test jest --watch", - "lint": "yarn eslint src", - "watch": "ts-node-dev --respawn --exit-child src/local.ts", - "build": "ncc build src/lambda.ts -o dist", - "dist": "yarn build && cd dist && zip ../webhook.zip index.js", - "format": "prettier --write \"**/*.ts\"", - "format-check": "prettier --check \"**/*.ts\"", - "all": "yarn build && yarn format && yarn lint && yarn test" - }, - "devDependencies": { - "@octokit/webhooks-definitions": "^3.67.3", - "@trivago/prettier-plugin-sort-imports": "^4.0.0", - "@types/aws-lambda": "^8.10.109", - "@types/express": "^4.17.15", - "@types/jest": "^29.2.4", - "@types/node": "^18.11.18", - "@typescript-eslint/eslint-plugin": "^5.47.1", - "@typescript-eslint/parser": "^5.47.1", - "@vercel/ncc": "0.36.0", - "body-parser": "^1.20.0", - "eslint": "^8.30.0", - "eslint-plugin-prettier": "4.2.1", - "express": "^4.18.2", - "jest": "^29.3", - "jest-mock": "^29.3.1", - "nock": "^13.2.9", - "prettier": "2.8.1", - "ts-jest": "^29.0.3", - "ts-node-dev": "^2.0.0", - "typescript": "^4.9.4" - }, - "dependencies": { - "@aws-sdk/client-ssm": "^3.238.0", - "@octokit/rest": "^19.0.5", - "@octokit/webhooks": "^10.4.0", - "aws-lambda": "^1.0.7", - "aws-sdk": "^2.1283.0", - "tslog": "^3.3.4" - } -} diff --git a/modules/webhook/lambdas/webhook/src/lambda.ts b/modules/webhook/lambdas/webhook/src/lambda.ts deleted file mode 100644 index 7dfe19a0b6..0000000000 --- a/modules/webhook/lambdas/webhook/src/lambda.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { APIGatewayEvent, Context } from 'aws-lambda'; - -import { handle } from './webhook/handler'; -import { logger } from './webhook/logger'; - -export interface Response { - statusCode: number; - body?: string; -} -export async function githubWebhook(event: APIGatewayEvent, context: Context): Promise { - logger.setSettings({ requestId: context.awsRequestId }); - logger.debug(JSON.stringify(event)); - let result: Response; - try { - result = await handle(event.headers, event.body as string); - } catch (e) { - logger.error(e); - result = { - statusCode: 500, - body: 'Check the Lambda logs for the error details.', - }; - } - return result; -} diff --git a/modules/webhook/lambdas/webhook/src/sqs/index.test.ts b/modules/webhook/lambdas/webhook/src/sqs/index.test.ts deleted file mode 100644 index 32761e4526..0000000000 --- a/modules/webhook/lambdas/webhook/src/sqs/index.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { SQS } from 'aws-sdk'; - -import { ActionRequestMessage, GithubWorkflowEvent, sendActionRequest, sendWebhookEventToWorkflowJobQueue } from '.'; -import workflowjob_event from '../../test/resources/github_workflowjob_event.json'; - -const mockSQS = { - sendMessage: jest.fn(() => { - { - return { promise: jest.fn() }; - } - }), -}; -jest.mock('aws-sdk', () => ({ - SQS: jest.fn().mockImplementation(() => mockSQS), -})); - -describe('Test sending message to SQS.', () => { - const message: ActionRequestMessage = { - eventType: 'type', - id: 0, - installationId: 0, - repositoryName: 'test', - repositoryOwner: 'owner', - }; - const sqsMessage: SQS.Types.SendMessageRequest = { - QueueUrl: 'https://sqs.eu-west-1.amazonaws.com/123456789/queued-builds', - MessageBody: JSON.stringify(message), - }; - afterEach(() => { - jest.clearAllMocks(); - }); - it('no fifo queue, based on defaults', async () => { - // Arrange - process.env.SQS_URL_WEBHOOK = sqsMessage.QueueUrl; - - // Act - const result = await sendActionRequest(message); - - // Assert - expect(mockSQS.sendMessage).toBeCalledWith(sqsMessage); - expect(result).resolves; - }); - - it('no fifo queue', async () => { - // Arrange - process.env.SQS_URL_WEBHOOK = sqsMessage.QueueUrl; - process.env.SQS_IS_FIFO = 'false'; - - // Act - const result = await sendActionRequest(message); - - // Assert - expect(mockSQS.sendMessage).toBeCalledWith(sqsMessage); - expect(result).resolves; - }); - - it('use a fifo queue', async () => { - // Arrange - process.env.SQS_URL_WEBHOOK = sqsMessage.QueueUrl; - process.env.SQS_IS_FIFO = 'true'; - - // Act - const result = await sendActionRequest(message); - - // Assert - expect(mockSQS.sendMessage).toBeCalledWith({ ...sqsMessage, MessageGroupId: String(message.id) }); - expect(result).resolves; - }); -}); -describe('Test sending message to SQS.', () => { - const message: GithubWorkflowEvent = { - workflowJobEvent: JSON.parse(JSON.stringify(workflowjob_event)), - }; - const sqsMessage: SQS.Types.SendMessageRequest = { - QueueUrl: 'https://sqs.eu-west-1.amazonaws.com/123456789/webhook_events_workflow_job_queue', - MessageBody: JSON.stringify(message), - }; - afterEach(() => { - jest.clearAllMocks(); - }); - it('sends webhook events to workflow job queue', async () => { - // Arrange - process.env.SQS_WORKFLOW_JOB_QUEUE = sqsMessage.QueueUrl; - - // Act - const result = await sendWebhookEventToWorkflowJobQueue(message); - - // Assert - expect(mockSQS.sendMessage).toBeCalledWith(sqsMessage); - expect(result).resolves; - }); - it('Does not send webhook events to workflow job event copy queue', async () => { - // Arrange - process.env.SQS_WORKFLOW_JOB_QUEUE = ''; - // Act - await sendWebhookEventToWorkflowJobQueue(message); - - // Assert - expect(mockSQS.sendMessage).not.toBeCalledWith(sqsMessage); - }); -}); diff --git a/modules/webhook/lambdas/webhook/src/sqs/index.ts b/modules/webhook/lambdas/webhook/src/sqs/index.ts deleted file mode 100644 index a8c3dd08a2..0000000000 --- a/modules/webhook/lambdas/webhook/src/sqs/index.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { WorkflowJobEvent } from '@octokit/webhooks-types'; -import { SQS } from 'aws-sdk'; - -import { LogFields, logger } from '../webhook/logger'; - -export interface ActionRequestMessage { - id: number; - eventType: string; - repositoryName: string; - repositoryOwner: string; - installationId: number; -} -export interface GithubWorkflowEvent { - workflowJobEvent: WorkflowJobEvent; -} - -export const sendActionRequest = async (message: ActionRequestMessage): Promise => { - const sqs = new SQS({ region: process.env.AWS_REGION }); - - const useFifoQueueEnv = process.env.SQS_IS_FIFO || 'false'; - const useFifoQueue = JSON.parse(useFifoQueueEnv) as boolean; - - const sqsMessage: SQS.Types.SendMessageRequest = { - QueueUrl: String(process.env.SQS_URL_WEBHOOK), - MessageBody: JSON.stringify(message), - }; - - logger.debug(`sending message to SQS: ${JSON.stringify(sqsMessage)}`, LogFields.print()); - if (useFifoQueue) { - sqsMessage.MessageGroupId = String(message.id); - } - - await sqs.sendMessage(sqsMessage).promise(); -}; - -export const sendWebhookEventToWorkflowJobQueue = async (message: GithubWorkflowEvent): Promise => { - const webhook_events_workflow_job_queue = process.env.SQS_WORKFLOW_JOB_QUEUE || undefined; - - if (webhook_events_workflow_job_queue != undefined) { - const sqs = new SQS({ region: process.env.AWS_REGION }); - const sqsMessage: SQS.Types.SendMessageRequest = { - QueueUrl: String(process.env.SQS_WORKFLOW_JOB_QUEUE), - MessageBody: JSON.stringify(message), - }; - logger.debug( - `Sending Webhook events to the workflow job queue: ${webhook_events_workflow_job_queue}`, - LogFields.print(), - ); - try { - await sqs.sendMessage(sqsMessage).promise(); - } catch (e) { - logger.warn(`Error in sending webhook events to workflow job queue: ${(e as Error).message}`, LogFields.print()); - } - } -}; diff --git a/modules/webhook/lambdas/webhook/src/ssm/index.test.ts b/modules/webhook/lambdas/webhook/src/ssm/index.test.ts deleted file mode 100644 index 0f002dbacf..0000000000 --- a/modules/webhook/lambdas/webhook/src/ssm/index.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { GetParameterCommandOutput, SSM } from '@aws-sdk/client-ssm'; -import nock from 'nock'; - -import { getParameterValue } from '.'; - -jest.mock('@aws-sdk/client-ssm'); - -const cleanEnv = process.env; -const ENVIRONMENT = 'dev'; - -beforeEach(() => { - jest.resetModules(); - jest.clearAllMocks(); - process.env = { ...cleanEnv }; - nock.disableNetConnect(); -}); - -describe('Test getParameterValue', () => { - test('Gets parameters and returns string', async () => { - // Arrange - const parameterValue = 'test'; - const parameterName = 'testParam'; - const output: GetParameterCommandOutput = { - Parameter: { - Name: parameterName, - Type: 'SecureString', - Value: parameterValue, - }, - $metadata: { - httpStatusCode: 200, - }, - }; - - SSM.prototype.getParameter = jest.fn().mockResolvedValue(output); - - // Act - const result = await getParameterValue(ENVIRONMENT, parameterName); - - // Assert - expect(result).toBe(parameterValue); - }); -}); diff --git a/modules/webhook/lambdas/webhook/src/ssm/index.ts b/modules/webhook/lambdas/webhook/src/ssm/index.ts deleted file mode 100644 index 9215ab6cb6..0000000000 --- a/modules/webhook/lambdas/webhook/src/ssm/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { SSM } from '@aws-sdk/client-ssm'; - -export async function getParameterValue(environment: string, name: string): Promise { - const parameter_name = `/actions_runner/${environment}/${name}`; - const client = new SSM({ region: process.env.AWS_REGION as string }); - return (await client.getParameter({ Name: parameter_name, WithDecryption: true })).Parameter?.Value as string; -} diff --git a/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts b/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts deleted file mode 100644 index 0258407fd2..0000000000 --- a/modules/webhook/lambdas/webhook/src/webhook/handler.test.ts +++ /dev/null @@ -1,328 +0,0 @@ -import { Webhooks } from '@octokit/webhooks'; -import { mocked } from 'jest-mock'; -import nock from 'nock'; - -import checkrun_event from '../../test/resources/github_check_run_event.json'; -import workflowjob_event from '../../test/resources/github_workflowjob_event.json'; -import { sendActionRequest, sendWebhookEventToWorkflowJobQueue } from '../sqs'; -import { getParameterValue } from '../ssm'; -import { handle } from './handler'; - -jest.mock('../sqs'); -jest.mock('../ssm'); - -const GITHUB_APP_WEBHOOK_SECRET = 'TEST_SECRET'; - -const secret = 'TEST_SECRET'; -const webhooks = new Webhooks({ - secret: secret, -}); - -describe('handler', () => { - let originalError: Console['error']; - - beforeEach(() => { - nock.disableNetConnect(); - process.env.REPOSITORY_WHITE_LIST = '[]'; - originalError = console.error; - console.error = jest.fn(); - jest.clearAllMocks(); - jest.resetAllMocks(); - - const mockedGet = mocked(getParameterValue); - mockedGet.mockResolvedValueOnce(GITHUB_APP_WEBHOOK_SECRET); - }); - - afterEach(() => { - console.error = originalError; - }); - - it('returns 500 if no signature available', async () => { - const resp = await handle({}, ''); - expect(resp.statusCode).toBe(500); - }); - - it('returns 401 if signature is invalid', async () => { - const resp = await handle({ 'X-Hub-Signature': 'bbb' }, 'aaaa'); - expect(resp.statusCode).toBe(401); - }); - - describe('Test for workflowjob event: ', () => { - beforeEach(() => { - process.env.DISABLE_CHECK_WORKFLOW_JOB_LABELS = 'false'; - }); - it('handles workflow job events', async () => { - const event = JSON.stringify(workflowjob_event); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('handles workflow job events with 256 hash signature', async () => { - const event = JSON.stringify(workflowjob_event); - const resp = await handle( - { 'X-Hub-Signature-256': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('does not handle other events', async () => { - const event = JSON.stringify(workflowjob_event); - const resp = await handle({ 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'push' }, event); - expect(resp.statusCode).toBe(202); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('does not handle workflow_job events with actions other than queued (action = started)', async () => { - const event = JSON.stringify({ ...workflowjob_event, action: 'started' }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('does not handle workflow_job events with actions other than queued (action = completed)', async () => { - const event = JSON.stringify({ ...workflowjob_event, action: 'completed' }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('does not handle workflow_job events from unlisted repositories', async () => { - const event = JSON.stringify(workflowjob_event); - process.env.REPOSITORY_WHITE_LIST = '["NotCodertocat/Hello-World"]'; - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(403); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('handles workflow_job events without installation id', async () => { - const event = JSON.stringify({ ...workflowjob_event, installation: null }); - process.env.REPOSITORY_WHITE_LIST = '["philips-labs/terraform-aws-github-runner"]'; - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('handles workflow_job events from whitelisted repositories', async () => { - const event = JSON.stringify(workflowjob_event); - process.env.REPOSITORY_WHITE_LIST = '["philips-labs/terraform-aws-github-runner"]'; - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('Check runner labels accept test job', async () => { - process.env.RUNNER_LABELS = '["self-hosted", "test"]'; - process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK = 'true'; - process.env.WORKFLOW_JOB_LABELS_CHECK_ALL = 'true'; - const event = JSON.stringify({ - ...workflowjob_event, - workflow_job: { - ...workflowjob_event.workflow_job, - labels: ['self-hosted', 'Test'], - }, - }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('Check runner labels accept job with mixed order.', async () => { - process.env.RUNNER_LABELS = '["linux", "TEST", "self-hosted"]'; - process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK = 'true'; - process.env.WORKFLOW_JOB_LABELS_CHECK_ALL = 'true'; - const event = JSON.stringify({ - ...workflowjob_event, - workflow_job: { - ...workflowjob_event.workflow_job, - labels: ['linux', 'self-hosted', 'test'], - }, - }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('Check webhook accept jobs where not all labels are provided in job.', async () => { - process.env.RUNNER_LABELS = '["self-hosted", "test", "test2"]'; - process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK = 'true'; - process.env.WORKFLOW_JOB_LABELS_CHECK_ALL = 'true'; - const event = JSON.stringify({ - ...workflowjob_event, - workflow_job: { - ...workflowjob_event.workflow_job, - labels: ['self-hosted'], - }, - }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('Check webhook does not accept jobs where not all labels are supported by the runner.', async () => { - process.env.RUNNER_LABELS = '["self-hosted", "x64", "linux", "test"]'; - process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK = 'true'; - process.env.WORKFLOW_JOB_LABELS_CHECK_ALL = 'true'; - const event = JSON.stringify({ - ...workflowjob_event, - workflow_job: { - ...workflowjob_event.workflow_job, - labels: ['self-hosted', 'linux', 'x64', 'test', 'gpu'], - }, - }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(202); - expect(sendActionRequest).not.toBeCalled; - }); - - it('Check webhook will accept jobs with a single acceptable label.', async () => { - process.env.RUNNER_LABELS = '["self-hosted", "x64", "linux", "test"]'; - process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK = 'true'; - process.env.WORKFLOW_JOB_LABELS_CHECK_ALL = 'false'; - const event = JSON.stringify({ - ...workflowjob_event, - workflow_job: { - ...workflowjob_event.workflow_job, - labels: ['x64'], - }, - }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('Check webhook will not accept jobs without correct label when job label check all is false.', async () => { - process.env.RUNNER_LABELS = '["self-hosted", "x64", "linux", "test"]'; - process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK = 'true'; - process.env.WORKFLOW_JOB_LABELS_CHECK_ALL = 'false'; - const event = JSON.stringify({ - ...workflowjob_event, - workflow_job: { - ...workflowjob_event.workflow_job, - labels: ['ubuntu-latest'], - }, - }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(202); - expect(sendActionRequest).not.toBeCalled; - }); - }); - - describe('Test for check_run event (legacy): ', () => { - it('handles check_run events', async () => { - const event = JSON.stringify(checkrun_event); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('does not handle check_run events with actions other than queued (action = started)', async () => { - const event = JSON.stringify({ ...checkrun_event, action: 'started' }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('does not handle check_run events with actions other than queued (action = completed)', async () => { - const event = JSON.stringify({ ...checkrun_event, action: 'completed' }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('does not handle check_run events from unlisted repositories', async () => { - const event = JSON.stringify(checkrun_event); - process.env.REPOSITORY_WHITE_LIST = '["NotCodertocat/Hello-World"]'; - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, - event, - ); - expect(resp.statusCode).toBe(403); - expect(sendActionRequest).not.toBeCalled(); - }); - - it('handles check_run events from whitelisted repositories', async () => { - const event = JSON.stringify(checkrun_event); - process.env.REPOSITORY_WHITE_LIST = '["Codertocat/Hello-World"]'; - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - - it('handles check_run events with no installation id.', async () => { - const event = JSON.stringify({ ...checkrun_event, installation: { id: null } }); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'check_run' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendActionRequest).toBeCalled(); - }); - }); - - describe('Test for webhook events to be sent to workflow job queue: ', () => { - beforeEach(() => { - process.env.SQS_WORKFLOW_JOB_QUEUE = - 'https://sqs.eu-west-1.amazonaws.com/123456789/webhook_events_workflow_job_queue'; - }); - it('sends webhook events to workflow job queue', async () => { - const event = JSON.stringify(workflowjob_event); - const resp = await handle( - { 'X-Hub-Signature': await webhooks.sign(event), 'X-GitHub-Event': 'workflow_job' }, - event, - ); - expect(resp.statusCode).toBe(201); - expect(sendWebhookEventToWorkflowJobQueue).toBeCalled(); - }); - }); -}); diff --git a/modules/webhook/lambdas/webhook/src/webhook/handler.ts b/modules/webhook/lambdas/webhook/src/webhook/handler.ts deleted file mode 100644 index 8df6a6276d..0000000000 --- a/modules/webhook/lambdas/webhook/src/webhook/handler.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { Webhooks } from '@octokit/webhooks'; -import { CheckRunEvent, WorkflowJobEvent } from '@octokit/webhooks-types'; -import { IncomingHttpHeaders } from 'http'; - -import { Response } from '../lambda'; -import { sendActionRequest, sendWebhookEventToWorkflowJobQueue } from '../sqs'; -import { getParameterValue } from '../ssm'; -import { LogFields, logger as rootLogger } from './logger'; - -const supportedEvents = ['check_run', 'workflow_job']; -const logger = rootLogger.getChildLogger(); - -export async function handle(headers: IncomingHttpHeaders, body: string): Promise { - const { environment, repositoryWhiteList, enableWorkflowLabelCheck, workflowLabelCheckAll, runnerLabels } = - readEnvironmentVariables(); - - // ensure header keys lower case since github headers can contain capitals. - for (const key in headers) { - headers[key.toLowerCase()] = headers[key]; - } - - const githubEvent = headers['x-github-event'] as string; - - let response: Response = { - statusCode: await verifySignature(githubEvent, headers, body, environment), - }; - - if (response.statusCode != 200) { - return response; - } - - if (!supportedEvents.includes(githubEvent)) { - logger.warn(`Unsupported event type.`, LogFields.print()); - return { - statusCode: 202, - body: `Ignoring unsupported event ${githubEvent}`, - }; - } - - const payload = JSON.parse(body); - LogFields.fields.event = githubEvent; - LogFields.fields.repository = payload.repository.full_name; - LogFields.fields.action = payload.action; - LogFields.fields.name = payload[githubEvent].name; - LogFields.fields.status = payload[githubEvent].status; - LogFields.fields.workflowJobId = payload[githubEvent].id; - LogFields.fields.started_at = payload[githubEvent]?.started_at; - - /* - The app subscribes to all `check_run` and `workflow_job` events. - If the event status is `completed`, log the data for workflow metrics. - */ - LogFields.fields.completed_at = payload[githubEvent]?.completed_at; - LogFields.fields.conclusion = payload[githubEvent]?.conclusion; - - if (isRepoNotAllowed(payload.repository.full_name, repositoryWhiteList)) { - logger.error(`Received event from unauthorized repository ${payload.repository.full_name}`, LogFields.print()); - return { - statusCode: 403, - }; - } - - logger.info(`Processing Github event`, LogFields.print()); - - if (githubEvent == 'workflow_job') { - const workflowEventPayload = payload as WorkflowJobEvent; - response = await handleWorkflowJob( - workflowEventPayload, - githubEvent, - enableWorkflowLabelCheck, - workflowLabelCheckAll, - runnerLabels, - ); - await sendWorkflowJobEvents(githubEvent, workflowEventPayload); - } else if (githubEvent == 'check_run') { - response = await handleCheckRun(payload as CheckRunEvent, githubEvent); - } - - return response; -} -async function sendWorkflowJobEvents(githubEvent: string, workflowEventPayload: WorkflowJobEvent) { - await sendWebhookEventToWorkflowJobQueue({ - workflowJobEvent: workflowEventPayload, - }); -} - -function readEnvironmentVariables() { - const environment = process.env.ENVIRONMENT; - const enableWorkflowLabelCheckEnv = process.env.ENABLE_WORKFLOW_JOB_LABELS_CHECK || 'false'; - const enableWorkflowLabelCheck = JSON.parse(enableWorkflowLabelCheckEnv) as boolean; - const workflowLabelCheckAllEnv = process.env.WORKFLOW_JOB_LABELS_CHECK_ALL || 'false'; - const workflowLabelCheckAll = JSON.parse(workflowLabelCheckAllEnv) as boolean; - const repositoryWhiteListEnv = process.env.REPOSITORY_WHITE_LIST || '[]'; - const repositoryWhiteList = JSON.parse(repositoryWhiteListEnv) as Array; - const runnerLabelsEnv = (process.env.RUNNER_LABELS || '[]').toLowerCase(); - const runnerLabels = JSON.parse(runnerLabelsEnv) as Array; - return { environment, repositoryWhiteList, enableWorkflowLabelCheck, workflowLabelCheckAll, runnerLabels }; -} - -async function verifySignature( - githubEvent: string, - headers: IncomingHttpHeaders, - body: string, - environment: string, -): Promise { - let signature; - if ('x-hub-signature-256' in headers) { - signature = headers['x-hub-signature-256'] as string; - } else { - signature = headers['x-hub-signature'] as string; - } - if (!signature) { - logger.error( - "Github event doesn't have signature. This webhook requires a secret to be configured.", - LogFields.print(), - ); - return 500; - } - - const secret = await getParameterValue(environment, 'github_app_webhook_secret'); - - const webhooks = new Webhooks({ - secret: secret, - }); - if (!(await webhooks.verify(body, signature))) { - logger.error('Unable to verify signature!', LogFields.print()); - return 401; - } - return 200; -} - -async function handleWorkflowJob( - body: WorkflowJobEvent, - githubEvent: string, - enableWorkflowLabelCheck: boolean, - workflowLabelCheckAll: boolean, - runnerLabels: string[], -): Promise { - if (enableWorkflowLabelCheck && !canRunJob(body, runnerLabels, workflowLabelCheckAll)) { - logger.warn( - `Received event contains runner labels '${body.workflow_job.labels}' that are not accepted.`, - LogFields.print(), - ); - return { - statusCode: 202, - body: `Received event contains runner labels '${body.workflow_job.labels}' that are not accepted.`, - }; - } - - const installationId = getInstallationId(body); - if (body.action === 'queued') { - await sendActionRequest({ - id: body.workflow_job.id, - repositoryName: body.repository.name, - repositoryOwner: body.repository.owner.login, - eventType: githubEvent, - installationId: installationId, - }); - logger.info(`Successfully queued job for ${body.repository.full_name}`, LogFields.print()); - } - return { statusCode: 201 }; -} - -async function handleCheckRun(body: CheckRunEvent, githubEvent: string): Promise { - const installationId = getInstallationId(body); - if (body.action === 'created' && body.check_run.status === 'queued') { - await sendActionRequest({ - id: body.check_run.id, - repositoryName: body.repository.name, - repositoryOwner: body.repository.owner.login, - eventType: githubEvent, - installationId: installationId, - }); - } - logger.info(`Successfully queued job for ${body.repository.full_name}`, LogFields.print()); - return { statusCode: 201 }; -} - -function getInstallationId(body: WorkflowJobEvent | CheckRunEvent) { - let installationId = body.installation?.id; - if (installationId == null) { - installationId = 0; - } - return installationId; -} - -function isRepoNotAllowed(repoFullName: string, repositoryWhiteList: string[]): boolean { - return repositoryWhiteList.length > 0 && !repositoryWhiteList.includes(repoFullName); -} - -function canRunJob(job: WorkflowJobEvent, runnerLabels: string[], workflowLabelCheckAll: boolean): boolean { - const workflowJobLabels = job.workflow_job.labels; - const match = workflowLabelCheckAll - ? workflowJobLabels.every((l) => runnerLabels.includes(l.toLowerCase())) - : workflowJobLabels.some((l) => runnerLabels.includes(l.toLowerCase())); - - logger.debug( - `Received workflow job event with labels: '${JSON.stringify(workflowJobLabels)}'. The event does ${ - match ? '' : 'NOT ' - }match the runner labels: '${Array.from(runnerLabels).join(',')}'`, - LogFields.print(), - ); - return match; -} diff --git a/modules/webhook/lambdas/webhook/src/webhook/logger.ts b/modules/webhook/lambdas/webhook/src/webhook/logger.ts deleted file mode 100644 index 9727c3b253..0000000000 --- a/modules/webhook/lambdas/webhook/src/webhook/logger.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Logger } from 'tslog'; - -export const logger = new Logger({ - colorizePrettyLogs: false, - displayInstanceName: false, - minLevel: process.env.LOG_LEVEL || 'info', - name: 'webhook', - overwriteConsole: true, - type: process.env.LOG_TYPE || 'pretty', -}); - -export class LogFields { - static fields: { [key: string]: string } = {}; - - public static print(): string { - return JSON.stringify(LogFields.fields); - } -} diff --git a/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts b/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts deleted file mode 100644 index d6972fd986..0000000000 --- a/modules/webhook/lambdas/webhook/src/webhook/modules.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare namespace NodeJS { - export interface ProcessEnv { - ENVIRONMENT: string; - LOG_LEVEL: 'silly' | 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; - LOG_TYPE: 'json' | 'pretty' | 'hidden'; - REPOSITORY_WHITE_LIST: string; - RUNNER_LABELS: string; - } -} diff --git a/modules/webhook/lambdas/webhook/tsconfig.json b/modules/webhook/lambdas/webhook/tsconfig.json deleted file mode 100644 index 764f2f6ae0..0000000000 --- a/modules/webhook/lambdas/webhook/tsconfig.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "compilerOptions": { - /* Basic Options */ - "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, - "outDir": "build", - "lib": [ - "es2020", - "DOM" - ] /* Specify library files to be included in the compilation. */, - "allowJs": true /* Allow javascript files to be compiled. */, - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - // "outDir": "./", /* Redirect output structure to the directory. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "incremental": true, /* Enable incremental compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - "downlevelIteration": true /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */, - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Strict Type-Checking Options */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - /* Module Resolution Options */ - "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [] /* List of folders to include type definitions from. */, - // "types": [] /* Type declaration files to be included in compilation. */, - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - /* Experimental Options */ - "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, - "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, - "resolveJsonModule": true, - "sourceMap": true - }, - "include": [ - "src/**/*" - ] -} diff --git a/modules/webhook/lambdas/webhook/yarn.lock b/modules/webhook/lambdas/webhook/yarn.lock deleted file mode 100644 index 6bccea807b..0000000000 --- a/modules/webhook/lambdas/webhook/yarn.lock +++ /dev/null @@ -1,5269 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== - dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@aws-crypto/ie11-detection@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-2.0.0.tgz#bb6c2facf8f03457e949dcf0921477397ffa4c6e" - integrity sha512-pkVXf/dq6PITJ0jzYZ69VhL8VFOFoPZLZqtU/12SGnzYuJOOGNfF41q9GxdI1yqC8R13Rq3jOLKDFpUJFT5eTA== - dependencies: - tslib "^1.11.1" - -"@aws-crypto/sha256-browser@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-2.0.0.tgz#741c9024df55ec59b51e5b1f5d806a4852699fb5" - integrity sha512-rYXOQ8BFOaqMEHJrLHul/25ckWH6GTJtdLSajhlqGMx0PmSueAuvboCuZCTqEKlxR8CQOwRarxYMZZSYlhRA1A== - dependencies: - "@aws-crypto/ie11-detection" "^2.0.0" - "@aws-crypto/sha256-js" "^2.0.0" - "@aws-crypto/supports-web-crypto" "^2.0.0" - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@2.0.0", "@aws-crypto/sha256-js@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-2.0.0.tgz#f1f936039bdebd0b9e2dd834d65afdc2aac4efcb" - integrity sha512-VZY+mCY4Nmrs5WGfitmNqXzaE873fcIZDu54cbaDaaamsaTOP1DBImV9F4pICc3EHjQXujyE8jig+PFCaew9ig== - dependencies: - "@aws-crypto/util" "^2.0.0" - "@aws-sdk/types" "^3.1.0" - tslib "^1.11.1" - -"@aws-crypto/supports-web-crypto@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-2.0.0.tgz#fd6cde30b88f77d5a4f57b2c37c560d918014f9e" - integrity sha512-Ge7WQ3E0OC7FHYprsZV3h0QIcpdyJLvIeg+uTuHqRYm8D6qCFJoiC+edSzSyFiHtZf+NOQDJ1q46qxjtzIY2nA== - dependencies: - tslib "^1.11.1" - -"@aws-crypto/util@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-2.0.0.tgz#17ba6f83c7e447b70fc24b84c5f6714d1e329f4a" - integrity sha512-YDooyH83m2P5A3h6lNH7hm6mIP93sU/dtzRmXIgtO4BCB7SvtX8ysVKQAE8tVky2DQ3HHxPCjNTuUe7YoAMrNQ== - dependencies: - "@aws-sdk/types" "^3.1.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-sdk/abort-controller@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/abort-controller/-/abort-controller-3.226.0.tgz#3adffb8ee5af57ddb154e8544a8eeec76ad32271" - integrity sha512-cJVzr1xxPBd08voknXvR0RLgtZKGKt6WyDpH/BaPCu3rfSqWCDZKzwqe940eqosjmKrxC6pUZNKASIqHOQ8xxQ== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/client-ssm@^3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-ssm/-/client-ssm-3.238.0.tgz#238863d6e2cf1fde0da241c8eaf70ea88682443b" - integrity sha512-pHsRbaeoa2V3ck0KL5f9538UQrIF1WEjH1x2kyn/cRyU/fEvSTLJQwf2CL2qMl8CBTuWu/Zn1FlKHgWB7h05VA== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/client-sts" "3.238.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/credential-provider-node" "3.238.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-signing" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - "@aws-sdk/util-waiter" "3.226.0" - tslib "^2.3.1" - uuid "^8.3.2" - -"@aws-sdk/client-sso-oidc@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.238.0.tgz#95aa2e993b6bff2adc74d1821241f80f9ea5b283" - integrity sha512-kazcA2Kp+cXQRtaZi5/T5YFfU9J3nzu1tXJsh0xAm+J3S9LS1ertY1bSX6KBed2xuxx2mfum8JRqli0TJad/pA== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/client-sso@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.238.0.tgz#dcb4df1e97e6e8821f473e70eee81a8d4424664f" - integrity sha512-KHJJWP7hBDa9KLYiU5+hOb+3AAba93PhWebXkpKyQ/Bs+e7ECCreyLCwuME6uWTV01NDuFDpwZ6zUMpyNIcP6Q== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/client-sts@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.238.0.tgz#b814c2cf888cf99be199c25ede851dfcc8ae5ec6" - integrity sha512-jQNwHqxWUGvWCN4o8KUFYQES8r41Oobu7x1KZOMrPhPxy27FUcDjBq/h85VoD2/AZlETSCZLiCnKV3KBh5pT5w== - dependencies: - "@aws-crypto/sha256-browser" "2.0.0" - "@aws-crypto/sha256-js" "2.0.0" - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/credential-provider-node" "3.238.0" - "@aws-sdk/fetch-http-handler" "3.226.0" - "@aws-sdk/hash-node" "3.226.0" - "@aws-sdk/invalid-dependency" "3.226.0" - "@aws-sdk/middleware-content-length" "3.226.0" - "@aws-sdk/middleware-endpoint" "3.226.0" - "@aws-sdk/middleware-host-header" "3.226.0" - "@aws-sdk/middleware-logger" "3.226.0" - "@aws-sdk/middleware-recursion-detection" "3.226.0" - "@aws-sdk/middleware-retry" "3.235.0" - "@aws-sdk/middleware-sdk-sts" "3.226.0" - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/middleware-signing" "3.226.0" - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/middleware-user-agent" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/node-http-handler" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/smithy-client" "3.234.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - "@aws-sdk/util-body-length-browser" "3.188.0" - "@aws-sdk/util-body-length-node" "3.208.0" - "@aws-sdk/util-defaults-mode-browser" "3.234.0" - "@aws-sdk/util-defaults-mode-node" "3.234.0" - "@aws-sdk/util-endpoints" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - "@aws-sdk/util-user-agent-browser" "3.226.0" - "@aws-sdk/util-user-agent-node" "3.226.0" - "@aws-sdk/util-utf8-browser" "3.188.0" - "@aws-sdk/util-utf8-node" "3.208.0" - fast-xml-parser "4.0.11" - tslib "^2.3.1" - -"@aws-sdk/config-resolver@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.234.0.tgz#29d8936b713b7ee59b26b335d4f6715d644fc089" - integrity sha512-uZxy4wzllfvgCQxVc+Iqhde0NGAnfmV2hWR6ejadJaAFTuYNvQiRg9IqJy3pkyDPqXySiJ8Bom5PoJfgn55J/A== - dependencies: - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-config-provider" "3.208.0" - "@aws-sdk/util-middleware" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-env@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.226.0.tgz#0bcb89a9abc166b3a48f5c255b9fcabc4cb80daf" - integrity sha512-sd8uK1ojbXxaZXlthzw/VXZwCPUtU3PjObOfr3Evj7MPIM2IH8h29foOlggx939MdLQGboJf9gKvLlvKDWtJRA== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-imds@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.226.0.tgz#0a4558449eb261412b0490ea1c3242eb91659759" - integrity sha512-//z/COQm2AjYFI1Lb0wKHTQSrvLFTyuKLFQGPJsKS7DPoxGOCKB7hmYerlbl01IDoCxTdyL//TyyPxbZEOQD5Q== - dependencies: - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-ini@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.238.0.tgz#ff21f2a52c9867c34814c1548e8d2bd5f5dfb15a" - integrity sha512-WmPNtIYyUasjV7VQxvPNq7ihmx0vFsiKAtjNjjakdrt5TPoma4nUYb9tIG9SuG+kcp4DJIgRLJAgZtXbCcVimg== - dependencies: - "@aws-sdk/credential-provider-env" "3.226.0" - "@aws-sdk/credential-provider-imds" "3.226.0" - "@aws-sdk/credential-provider-process" "3.226.0" - "@aws-sdk/credential-provider-sso" "3.238.0" - "@aws-sdk/credential-provider-web-identity" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-node@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.238.0.tgz#cccd15fc5f8babb843fab7ec3b09b36d40a02c61" - integrity sha512-/RN5EyGfgdIIJdFzv+O0nSaHX1/F3anQjTIBeVg8GJ+82m+bDxMdALsG+NzkYnLilN9Uhc1lSNjLBCoPa5DSEg== - dependencies: - "@aws-sdk/credential-provider-env" "3.226.0" - "@aws-sdk/credential-provider-imds" "3.226.0" - "@aws-sdk/credential-provider-ini" "3.238.0" - "@aws-sdk/credential-provider-process" "3.226.0" - "@aws-sdk/credential-provider-sso" "3.238.0" - "@aws-sdk/credential-provider-web-identity" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-process@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.226.0.tgz#bcd73a6d31d1b3181917d56e54aacbee242b077f" - integrity sha512-iUDMdnrTvbvaCFhWwqyXrhvQ9+ojPqPqXhwZtY1X/Qaz+73S9gXBPJHZaZb2Ke0yKE1Ql3bJbKvmmxC/qLQMng== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-sso@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.238.0.tgz#3e99252faa3e8e8d86e2f0dc8e29813d96f570c2" - integrity sha512-i70V4bFlCVYey3QARJ6XxKEg/4YuoFRnePV2oK37UHOGpEn49uXKwVZqLjzJgFHln7BPlC06cWDqrHUQIMvYrQ== - dependencies: - "@aws-sdk/client-sso" "3.238.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/token-providers" "3.238.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/credential-provider-web-identity@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.226.0.tgz#2b7d20f93a40e2243c7e3857f54b103d19a946fb" - integrity sha512-CCpv847rLB0SFOHz2igvUMFAzeT2fD3YnY4C8jltuJoEkn0ITn1Hlgt13nTJ5BUuvyti2mvyXZHmNzhMIMrIlw== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/fetch-http-handler@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.226.0.tgz#350f78fc18fe9cb0a889ef4870838a8fcfa8855c" - integrity sha512-JewZPMNEBXfi1xVnRa7pVtK/zgZD8/lQ/YnD8pq79WuMa2cwyhDtr8oqCoqsPW+WJT5ScXoMtuHxN78l8eKWgg== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/querystring-builder" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-base64" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/hash-node@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/hash-node/-/hash-node-3.226.0.tgz#252d98bcbb1e13c8f26d9d416db03cf8cceac185" - integrity sha512-MdlJhJ9/Espwd0+gUXdZRsHuostB2WxEVAszWxobP0FTT9PnicqnfK7ExmW+DUAc0ywxtEbR3e0UND65rlSTVw== - dependencies: - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-buffer-from" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/invalid-dependency@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/invalid-dependency/-/invalid-dependency-3.226.0.tgz#74586f60859ed1813985e3d642066cc46d2e9d40" - integrity sha512-QXOYFmap8g9QzRjumcRCIo2GEZkdCwd7ePQW0OABWPhKHzlJ74vvBxywjU3s39EEBEluWXtZ7Iufg6GxZM4ifw== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/is-array-buffer@3.201.0": - version "3.201.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz#06e557adc284fac2f26071c2944ae01f61b95854" - integrity sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/middleware-content-length@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-content-length/-/middleware-content-length-3.226.0.tgz#6cc952049f6e3cdc3a3778c9dce9f2aee942b5fe" - integrity sha512-ksUzlHJN2JMuyavjA46a4sctvnrnITqt2tbGGWWrAuXY1mel2j+VbgnmJUiwHKUO6bTFBBeft5Vd1TSOb4JmiA== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-endpoint@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.226.0.tgz#d776480be4b5a9534c2805b7425be05497f840b7" - integrity sha512-EvLFafjtUxTT0AC9p3aBQu1/fjhWdIeK58jIXaNFONfZ3F8QbEYUPuF/SqZvJM6cWfOO9qwYKkRDbCSTYhprIg== - dependencies: - "@aws-sdk/middleware-serde" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/url-parser" "3.226.0" - "@aws-sdk/util-config-provider" "3.208.0" - "@aws-sdk/util-middleware" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-host-header@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.226.0.tgz#1e1ecb034929e0dbc532ae501fd93781438f9a24" - integrity sha512-haVkWVh6BUPwKgWwkL6sDvTkcZWvJjv8AgC8jiQuSl8GLZdzHTB8Qhi3IsfFta9HAuoLjxheWBE5Z/L0UrfhLA== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-logger@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.226.0.tgz#37fd0e62f555befd526b03748c3aab60dcefecf3" - integrity sha512-m9gtLrrYnpN6yckcQ09rV7ExWOLMuq8mMPF/K3DbL/YL0TuILu9i2T1W+JuxSX+K9FMG2HrLAKivE/kMLr55xA== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-recursion-detection@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.226.0.tgz#e149b9138e94d2fa70e7752ba6b1ccb537009706" - integrity sha512-mwRbdKEUeuNH5TEkyZ5FWxp6bL2UC1WbY+LDv6YjHxmSMKpAoOueEdtU34PqDOLrpXXxIGHDFmjeGeMfktyEcA== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-retry@3.235.0": - version "3.235.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-retry/-/middleware-retry-3.235.0.tgz#c0d938db85a771812204ed5e981eaf5eef6b580b" - integrity sha512-50WHbJGpD3SNp9763MAlHqIhXil++JdQbKejNpHg7HsJne/ao3ub+fDOfx//mMBjpzBV25BGd5UlfL6blrClSg== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/service-error-classification" "3.229.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-middleware" "3.226.0" - "@aws-sdk/util-retry" "3.229.0" - tslib "^2.3.1" - uuid "^8.3.2" - -"@aws-sdk/middleware-sdk-sts@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.226.0.tgz#e8a8cf42bba8963259546120cde1e408628863f9" - integrity sha512-NN9T/qoSD1kZvAT+VLny3NnlqgylYQcsgV3rvi/8lYzw/G/2s8VS6sm/VTWGGZhx08wZRv20MWzYu3bftcyqUg== - dependencies: - "@aws-sdk/middleware-signing" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-serde@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-serde/-/middleware-serde-3.226.0.tgz#c837ef33b34bec2af19a1c177a0c02a1ae20da5e" - integrity sha512-nPuOOAkSfx9TxzdKFx0X2bDlinOxGrqD7iof926K/AEflxGD1DBdcaDdjlYlPDW2CVE8LV/rAgbYuLxh/E/1VA== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-signing@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.226.0.tgz#ebb1d142ac2767466f2e464bb7dba9837143b4d1" - integrity sha512-E6HmtPcl+IjYDDzi1xI2HpCbBq2avNWcjvCriMZWuTAtRVpnA6XDDGW5GY85IfS3A8G8vuWqEVPr8JcYUcjfew== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/signature-v4" "3.226.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-middleware" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/middleware-stack@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-stack/-/middleware-stack-3.226.0.tgz#b0408370270188103987c457c758f9cf7651754f" - integrity sha512-85wF29LvPvpoed60fZGDYLwv1Zpd/cM0C22WSSFPw1SSJeqO4gtFYyCg2squfT3KI6kF43IIkOCJ+L7GtryPug== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/middleware-user-agent@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.226.0.tgz#26653189f3e8da86514f77688a80d0ad445c0799" - integrity sha512-N1WnfzCW1Y5yWhVAphf8OPGTe8Df3vmV7/LdsoQfmpkCZgLZeK2o0xITkUQhRj1mbw7yp8tVFLFV3R2lMurdAQ== - dependencies: - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/node-config-provider@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.226.0.tgz#a9e21512ef824142bb928a0b2f85b39a75b8964d" - integrity sha512-B8lQDqiRk7X5izFEUMXmi8CZLOKCTWQJU9HQf3ako+sF0gexo4nHN3jhoRWyLtcgC5S3on/2jxpAcqtm7kuY3w== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/node-http-handler@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.226.0.tgz#373886e949d214a99a3521bd6c141fa17b0e89fe" - integrity sha512-xQCddnZNMiPmjr3W7HYM+f5ir4VfxgJh37eqZwX6EZmyItFpNNeVzKUgA920ka1VPz/ZUYB+2OFGiX3LCLkkaA== - dependencies: - "@aws-sdk/abort-controller" "3.226.0" - "@aws-sdk/protocol-http" "3.226.0" - "@aws-sdk/querystring-builder" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/property-provider@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/property-provider/-/property-provider-3.226.0.tgz#ef0ff37c319dc37a52f08fa7544f861308a3bbd8" - integrity sha512-TsljjG+Sg0LmdgfiAlWohluWKnxB/k8xenjeozZfzOr5bHmNHtdbWv6BtNvD/R83hw7SFXxbJHlD5H4u9p2NFg== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/protocol-http@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/protocol-http/-/protocol-http-3.226.0.tgz#0af7bdc331508e556b722aad0cb78eefa93466e3" - integrity sha512-zWkVqiTA9RXL6y0hhfZc9bcU4DX2NI6Hw9IhQmSPeM59mdbPjJlY4bLlMr5YxywqO3yQ/ylNoAfrEzrDjlOSRg== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/querystring-builder@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-builder/-/querystring-builder-3.226.0.tgz#11cd751abeac66f1f9349225454bac3e39808926" - integrity sha512-LVurypuNeotO4lmirKXRC4NYrZRAyMJXuwO0f2a5ZAUJCjauwYrifKue6yCfU7bls7gut7nfcR6B99WBYpHs3g== - dependencies: - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-uri-escape" "3.201.0" - tslib "^2.3.1" - -"@aws-sdk/querystring-parser@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/querystring-parser/-/querystring-parser-3.226.0.tgz#ba6a26727c98d46c95180e6cdc463039c5e4740d" - integrity sha512-FzB+VrQ47KAFxiPt2YXrKZ8AOLZQqGTLCKHzx4bjxGmwgsjV8yIbtJiJhZLMcUQV4LtGeIY9ixIqQhGvnZHE4A== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/service-error-classification@3.229.0": - version "3.229.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/service-error-classification/-/service-error-classification-3.229.0.tgz#768f1eb92775ca2cc99c6451a2303a0008a28fc1" - integrity sha512-dnzWWQ0/NoWMUZ5C0DW3dPm0wC1O76Y/SpKbuJzWPkx1EYy6r8p32Ly4D9vUzrKDbRGf48YHIF2kOkBmu21CLg== - -"@aws-sdk/shared-ini-file-loader@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.226.0.tgz#d0ade86834b1803ce4b9dcab459e57e0376fd6cf" - integrity sha512-661VQefsARxVyyV2FX9V61V+nNgImk7aN2hYlFKla6BCwZfMng+dEtD0xVGyg1PfRw0qvEv5LQyxMVgHcUSevA== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/signature-v4@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4/-/signature-v4-3.226.0.tgz#100390b5c5b55a9b0abd05b06fceb36cfa0ecf98" - integrity sha512-/R5q5agdPd7HJB68XMzpxrNPk158EHUvkFkuRu5Qf3kkkHebEzWEBlWoVpUe6ss4rP9Tqcue6xPuaftEmhjpYw== - dependencies: - "@aws-sdk/is-array-buffer" "3.201.0" - "@aws-sdk/types" "3.226.0" - "@aws-sdk/util-hex-encoding" "3.201.0" - "@aws-sdk/util-middleware" "3.226.0" - "@aws-sdk/util-uri-escape" "3.201.0" - tslib "^2.3.1" - -"@aws-sdk/smithy-client@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.234.0.tgz#8f0021e021f0e52730ed0a8f271f839eb63bc374" - integrity sha512-8AtR/k4vsFvjXeQbIzq/Wy7Nbk48Ou0wUEeVYPHWHPSU8QamFWORkOwmKtKMfHAyZvmqiAPeQqHFkq+UJhWyyQ== - dependencies: - "@aws-sdk/middleware-stack" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/token-providers@3.238.0": - version "3.238.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.238.0.tgz#825306e82f24276e6aaa4850f36bba87418ba485" - integrity sha512-vYUwmy0kTzA99mJCVvad+/5RDlWve/xxnppT8DJK3JIdAgskp+rULY+joVnq2NSl489UAioUnFGs57vUxi8Pog== - dependencies: - "@aws-sdk/client-sso-oidc" "3.238.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/shared-ini-file-loader" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/types@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.226.0.tgz#3dba2ba223fbb8ac1ebc84de0e036ce69a81d469" - integrity sha512-MmmNHrWeO4man7wpOwrAhXlevqtOV9ZLcH4RhnG5LmRce0RFOApx24HoKENfFCcOyCm5LQBlsXCqi0dZWDWU0A== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/types@^3.1.0": - version "3.222.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.222.0.tgz#e61eb257f0ad2eaa65f7a72b9a2882f914fbcbb5" - integrity sha512-yXRYptInkfEFaOvWFxlRXsRh9jWOmQc1sZeKqjfx2UCtzNJ7ebedN0VfCz4SaDotcw9Q4JWuN66qhRMJjDx7/w== - -"@aws-sdk/url-parser@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/url-parser/-/url-parser-3.226.0.tgz#f53d1f868b27fe74aca091a799f2af56237b15a2" - integrity sha512-p5RLE0QWyP0OcTOLmFcLdVgUcUEzmEfmdrnOxyNzomcYb0p3vUagA5zfa1HVK2azsQJFBv28GfvMnba9bGhObg== - dependencies: - "@aws-sdk/querystring-parser" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-base64@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz#36b430e5396251f761590f7c2f0c5c12193f353c" - integrity sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg== - dependencies: - "@aws-sdk/util-buffer-from" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/util-body-length-browser@3.188.0": - version "3.188.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz#e1d949318c10a621b38575a9ef01e39f9857ddb0" - integrity sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-body-length-node@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz#baabd1fa1206ff2bd4ce3785122d86eb3258dd20" - integrity sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-buffer-from@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz#285e86f6dc9030148a4147d65239e75cb254a1b0" - integrity sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw== - dependencies: - "@aws-sdk/is-array-buffer" "3.201.0" - tslib "^2.3.1" - -"@aws-sdk/util-config-provider@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz#c485fd83fbac051337e5f6be60ea3f9fa61c0139" - integrity sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-defaults-mode-browser@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.234.0.tgz#1151f0beabdb46c1aaca42a1ad0714b8e686acaa" - integrity sha512-IHMKXjTbOD8XMz5+2oCOsVP94BYb9YyjXdns0aAXr2NAo7k2+RCzXQ2DebJXppGda1F6opFutoKwyVSN0cmbMw== - dependencies: - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - bowser "^2.11.0" - tslib "^2.3.1" - -"@aws-sdk/util-defaults-mode-node@3.234.0": - version "3.234.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.234.0.tgz#0607f1dc7a4dc896dfcaf377522535ca9ffba7a9" - integrity sha512-UGjQ+OjBYYhxFVtUY+jtr0ZZgzZh6OHtYwRhFt8IHewJXFCfZTyfsbX20szBj5y1S4HRIUJ7cwBLIytTqMbI5w== - dependencies: - "@aws-sdk/config-resolver" "3.234.0" - "@aws-sdk/credential-provider-imds" "3.226.0" - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/property-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-endpoints@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.226.0.tgz#3728b2e30f6f757ae862a0b7cf3991e75f252c3f" - integrity sha512-iqOkac/zLmyPBUJd7SLN0PeZMkOmlGgD5PHmmekTClOkce2eUjK9SNX1PzL73aXPoPTyhg9QGLH8uEZEQ8YUzg== - dependencies: - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-hex-encoding@3.201.0": - version "3.201.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz#21d7ec319240ee68c33d938e71cb79830bea315d" - integrity sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-locate-window@^3.0.0": - version "3.34.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.34.0.tgz#612cc17701cd712069fe7eea8b806731dfccd954" - integrity sha512-/xZs6dJ+00H/vNi4+tRoj32XfkhDCYWiASI/wVMzpZG/F15SOipe9MWxUWrH7FAm+BSp5cHcdnLtzFoJmI5cCQ== - dependencies: - tslib "^2.3.0" - -"@aws-sdk/util-middleware@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-middleware/-/util-middleware-3.226.0.tgz#7069ae96e2e00f6bb82c722e073922fb2b051ca2" - integrity sha512-B96CQnwX4gRvQdaQkdUtqvDPkrptV5+va6FVeJOocU/DbSYMAScLxtR3peMS8cnlOT6nL1Eoa42OI9AfZz1VwQ== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-retry@3.229.0": - version "3.229.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.229.0.tgz#17aad47b067e81acf644d5c2c0f2325f2d8faf4f" - integrity sha512-0zKTqi0P1inD0LzIMuXRIYYQ/8c1lWMg/cfiqUcIAF1TpatlpZuN7umU0ierpBFud7S+zDgg0oemh+Nj8xliJw== - dependencies: - "@aws-sdk/service-error-classification" "3.229.0" - tslib "^2.3.1" - -"@aws-sdk/util-uri-escape@3.201.0": - version "3.201.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz#5e708d4cde001a4558ee616f889ceacfadd2ab03" - integrity sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-user-agent-browser@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.226.0.tgz#164bb2da8d6353133784e47f0a0ae463bc9ebb73" - integrity sha512-PhBIu2h6sPJPcv2I7ELfFizdl5pNiL4LfxrasMCYXQkJvVnoXztHA1x+CQbXIdtZOIlpjC+6BjDcE0uhnpvfcA== - dependencies: - "@aws-sdk/types" "3.226.0" - bowser "^2.11.0" - tslib "^2.3.1" - -"@aws-sdk/util-user-agent-node@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.226.0.tgz#7569460b9efc6bbd5295275c51357e480ff469c2" - integrity sha512-othPc5Dz/pkYkxH+nZPhc1Al0HndQT8zHD4e9h+EZ+8lkd8n+IsnLfTS/mSJWrfiC6UlNRVw55cItstmJyMe/A== - dependencies: - "@aws-sdk/node-config-provider" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@aws-sdk/util-utf8-browser@3.188.0", "@aws-sdk/util-utf8-browser@^3.0.0": - version "3.188.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.188.0.tgz#484762bd600401350e148277731d6744a4a92225" - integrity sha512-jt627x0+jE+Ydr9NwkFstg3cUvgWh56qdaqAMDsqgRlKD21md/6G226z/Qxl7lb1VEW2LlmCx43ai/37Qwcj2Q== - dependencies: - tslib "^2.3.1" - -"@aws-sdk/util-utf8-node@3.208.0": - version "3.208.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-node/-/util-utf8-node-3.208.0.tgz#eba17de0f92f87b98481c2e2d0ceaa05c7994d67" - integrity sha512-jKY87Acv0yWBdFxx6bveagy5FYjz+dtV8IPT7ay1E2WPWH1czoIdMAkc8tSInK31T6CRnHWkLZ1qYwCbgRfERQ== - dependencies: - "@aws-sdk/util-buffer-from" "3.208.0" - tslib "^2.3.1" - -"@aws-sdk/util-waiter@3.226.0": - version "3.226.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-waiter/-/util-waiter-3.226.0.tgz#6715afd59748cbc610ddfbc5e21124b20a7e85ac" - integrity sha512-qYQMRxnu5k8qQihJXoIWMkBOj0+XkHHj/drLdbRnwL6ni6NcG8++cs9M3DSjIcxmxgF/7SLpDjn1H3sC7cYo4g== - dependencies: - "@aws-sdk/abort-controller" "3.226.0" - "@aws-sdk/types" "3.226.0" - tslib "^2.3.1" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" - integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/code-frame@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== - dependencies: - "@babel/highlight" "^7.18.6" - -"@babel/compat-data@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" - integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== - -"@babel/compat-data@^7.19.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.4.tgz#95c86de137bf0317f3a570e1b6e996b427299747" - integrity sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw== - -"@babel/core@7.17.8": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.8.tgz#3dac27c190ebc3a4381110d46c80e77efe172e1a" - integrity sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.7" - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.8" - "@babel/parser" "^7.17.8" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.3.tgz#2519f62a51458f43b682d61583c3810e7dcee64c" - integrity sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.3" - "@babel/helper-compilation-targets" "^7.19.3" - "@babel/helper-module-transforms" "^7.19.0" - "@babel/helpers" "^7.19.0" - "@babel/parser" "^7.19.3" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.3" - "@babel/types" "^7.19.3" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.7.tgz#8da2599beb4a86194a3b24df6c085931d9ee45ad" - integrity sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.17.3", "@babel/generator@^7.17.7", "@babel/generator@^7.19.3", "@babel/generator@^7.19.4", "@babel/generator@^7.7.2": - version "7.19.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.5.tgz#da3f4b301c8086717eee9cab14da91b1fa5dcca7" - integrity sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg== - dependencies: - "@babel/types" "^7.19.4" - "@jridgewell/gen-mapping" "^0.3.2" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.17.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" - integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== - dependencies: - "@babel/compat-data" "^7.18.8" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.19.3": - version "7.19.3" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz#a10a04588125675d7c7ae299af86fa1b2ee038ca" - integrity sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg== - dependencies: - "@babel/compat-data" "^7.19.3" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== - dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.17.7": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" - integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-module-transforms@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" - integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-plugin-utils@^7.18.6": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" - integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== - -"@babel/helper-simple-access@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" - integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.14.5": - version "7.14.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-identifier@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" - integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== - -"@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helpers@^7.17.8": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" - integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== - dependencies: - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helpers@^7.19.0": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.4.tgz#42154945f87b8148df7203a25c31ba9a73be46c5" - integrity sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.4" - "@babel/types" "^7.19.4" - -"@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== - dependencies: - "@babel/helper-validator-identifier" "^7.14.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" - integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539" - integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg== - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.15.4", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.17.8", "@babel/parser@^7.18.10", "@babel/parser@^7.18.6", "@babel/parser@^7.19.3", "@babel/parser@^7.19.4": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.6.tgz#b923430cb94f58a7eae8facbffa9efd19130e7f8" - integrity sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" - integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/template@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" - integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.6" - "@babel/types" "^7.18.6" - -"@babel/template@^7.3.3": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" - integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.15.4" - "@babel/types" "^7.15.4" - -"@babel/traverse@7.17.3": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.17.3", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.3", "@babel/traverse@^7.19.4", "@babel/traverse@^7.7.2": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.4.tgz#f117820e18b1e59448a6c1fa9d0ff08f7ac459a8" - integrity sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.19.4" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.19.4" - "@babel/types" "^7.19.4" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.0.0", "@babel/types@^7.15.4", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.19.3", "@babel/types@^7.19.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7" - integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw== - dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@cspotcode/source-map-support@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@eslint/eslintrc@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.0.tgz#8ec64e0df3e7a1971ee1ff5158da87389f167a63" - integrity sha512-7yfvXy6MWLgWSFsLhz5yH3iQ52St8cdUY6FoGieKkRDVxuxmrNuUetIuu6cmjNWwniUHiWXjxCr5tTXDrbYS5A== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^9.4.0" - globals "^13.19.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== - dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" - minimatch "^3.0.5" - -"@humanwhocodes/module-importer@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" - integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== - -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.3.1.tgz#3e3f876e4e47616ea3b1464b9fbda981872e9583" - integrity sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - -"@jest/core@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.3.1.tgz#bff00f413ff0128f4debec1099ba7dcd649774a1" - integrity sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/reporters" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.2.0" - jest-config "^29.3.1" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-resolve-dependencies "^29.3.1" - jest-runner "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - jest-watcher "^29.3.1" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.3.1.tgz#eb039f726d5fcd14698acd072ac6576d41cfcaa6" - integrity sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag== - dependencies: - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-mock "^29.3.1" - -"@jest/expect-utils@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.3.1.tgz#531f737039e9b9e27c42449798acb5bba01935b6" - integrity sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g== - dependencies: - jest-get-type "^29.2.0" - -"@jest/expect@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.3.1.tgz#456385b62894349c1d196f2d183e3716d4c6a6cd" - integrity sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg== - dependencies: - expect "^29.3.1" - jest-snapshot "^29.3.1" - -"@jest/fake-timers@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.3.1.tgz#b140625095b60a44de820876d4c14da1aa963f67" - integrity sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A== - dependencies: - "@jest/types" "^29.3.1" - "@sinonjs/fake-timers" "^9.1.2" - "@types/node" "*" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -"@jest/globals@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.3.1.tgz#92be078228e82d629df40c3656d45328f134a0c6" - integrity sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/types" "^29.3.1" - jest-mock "^29.3.1" - -"@jest/reporters@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.3.1.tgz#9a6d78c109608e677c25ddb34f907b90e07b4310" - integrity sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - jest-worker "^29.3.1" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.0.0": - version "29.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" - integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== - dependencies: - "@sinclair/typebox" "^0.24.1" - -"@jest/source-map@^29.2.0": - version "29.2.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" - integrity sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.3.1.tgz#92cd5099aa94be947560a24610aa76606de78f50" - integrity sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz#fa24b3b050f7a59d48f7ef9e0b782ab65123090d" - integrity sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA== - dependencies: - "@jest/test-result" "^29.3.1" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - slash "^3.0.0" - -"@jest/transform@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.3.1.tgz#1e6bd3da4af50b5c82a539b7b1f3770568d6e36d" - integrity sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.1" - -"@jest/types@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" - integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== - dependencies: - "@jest/schemas" "^29.0.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@1.4.14": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== - -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== - dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" - -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.14" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" - integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== - dependencies: - "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== - dependencies: - "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" - -"@octokit/auth-token@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.0.tgz#6f22c5fc56445c496628488ba6810131558fa4a9" - integrity sha512-MDNFUBcJIptB9At7HiV7VCvU3NcL4GnfCQaP8C5lrxWrRPMJBnemYtehaKSOlaM7AYxeRyj9etenu8LVpSpVaQ== - dependencies: - "@octokit/types" "^6.0.3" - -"@octokit/core@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.1.0.tgz#b6b03a478f1716de92b3f4ec4fd64d05ba5a9251" - integrity sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ== - dependencies: - "@octokit/auth-token" "^3.0.0" - "@octokit/graphql" "^5.0.0" - "@octokit/request" "^6.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^8.0.0" - before-after-hook "^2.2.0" - universal-user-agent "^6.0.0" - -"@octokit/endpoint@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.0.tgz#be758a1236d68d6bbb505e686dd50881c327a519" - integrity sha512-Kz/mIkOTjs9rV50hf/JK9pIDl4aGwAtT8pry6Rpy+hVXkAPhXanNQRxMoq6AeRgDCZR6t/A1zKniY2V1YhrzlQ== - dependencies: - "@octokit/types" "^6.0.3" - is-plain-object "^5.0.0" - universal-user-agent "^6.0.0" - -"@octokit/graphql@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.0.tgz#2cc6eb3bf8e0278656df1a7d0ca0d7591599e3b3" - integrity sha512-1ZZ8tX4lUEcLPvHagfIVu5S2xpHYXAmgN0+95eAOPoaVPzCfUXJtA5vASafcpWcO86ze0Pzn30TAx72aB2aguQ== - dependencies: - "@octokit/request" "^6.0.0" - "@octokit/types" "^6.0.3" - universal-user-agent "^6.0.0" - -"@octokit/openapi-types@^10.6.1": - version "10.6.1" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-10.6.1.tgz#4eb303e7da4de3d17216db80e3be6309f03b9fcc" - integrity sha512-53YKy8w8+sHQhUONhTiYt6MqNqPolejYr6rK/3VOevpORAIYGQEX2pmXnnhgdSsjHy176e5ZBgVt0ppOGziS7g== - -"@octokit/openapi-types@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a" - integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw== - -"@octokit/plugin-paginate-rest@^5.0.0": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-5.0.1.tgz#93d7e74f1f69d68ba554fa6b888c2a9cf1f99a83" - integrity sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw== - dependencies: - "@octokit/types" "^8.0.0" - -"@octokit/plugin-request-log@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" - integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== - -"@octokit/plugin-rest-endpoint-methods@^6.7.0": - version "6.7.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz#2f6f17f25b6babbc8b41d2bb0a95a8839672ce7c" - integrity sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw== - dependencies: - "@octokit/types" "^8.0.0" - deprecation "^2.3.1" - -"@octokit/request-error@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.0.tgz#f527d178f115a3b62d76ce4804dd5bdbc0270a81" - integrity sha512-WBtpzm9lR8z4IHIMtOqr6XwfkGvMOOILNLxsWvDwtzm/n7f5AWuqJTXQXdDtOvPfTDrH4TPhEvW2qMlR4JFA2w== - dependencies: - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.1.0.tgz#80bdac78dff583a8fa0978baeda139a71d98d10c" - integrity sha512-36V+sP4bJli31TRq8sea3d/Q1XGgZ9cnqpsegkLCnvpu+hoYephSkxGlWg4KB6dyUM1IWPXVrLFOKYzObQ+MZg== - dependencies: - "@octokit/endpoint" "^7.0.0" - "@octokit/request-error" "^3.0.0" - "@octokit/types" "^6.16.1" - is-plain-object "^5.0.0" - node-fetch "^2.6.7" - universal-user-agent "^6.0.0" - -"@octokit/rest@^19.0.5": - version "19.0.5" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.5.tgz#4dbde8ae69b27dca04b5f1d8119d282575818f6c" - integrity sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow== - dependencies: - "@octokit/core" "^4.1.0" - "@octokit/plugin-paginate-rest" "^5.0.0" - "@octokit/plugin-request-log" "^1.0.4" - "@octokit/plugin-rest-endpoint-methods" "^6.7.0" - -"@octokit/types@^6.0.3", "@octokit/types@^6.16.1": - version "6.31.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.31.1.tgz#223d062778bb6121635a022d3bf545d506fcc880" - integrity sha512-xkF46eaYcpT8ieO78mZWhMq3bt37zIsP5BUkN+zWgX+mTYDB7jOtUP1MOxcSF8hhJhsjjlB1YDgQAhX0z0oqPw== - dependencies: - "@octokit/openapi-types" "^10.6.1" - -"@octokit/types@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.0.0.tgz#93f0b865786c4153f0f6924da067fe0bb7426a9f" - integrity sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg== - dependencies: - "@octokit/openapi-types" "^14.0.0" - -"@octokit/webhooks-definitions@^3.67.3": - version "3.67.3" - resolved "https://registry.yarnpkg.com/@octokit/webhooks-definitions/-/webhooks-definitions-3.67.3.tgz#d2a905a90b04af8111982d0c13658a49fc4eecb9" - integrity sha512-do4Z1r2OVhuI0ihJhQ8Hg+yPWnBYEBNuFNCrvtPKoYT1w81jD7pBXgGe86lYuuNirkDHb0Nxt+zt4O5GiFJfgA== - -"@octokit/webhooks-methods@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-3.0.0.tgz#4f4443605233f46abc5f85a857ba105095aa1181" - integrity sha512-FAIyAchH9JUKXugKMC17ERAXM/56vVJekwXOON46pmUDYfU7uXB4cFY8yc8nYr5ABqVI7KjRKfFt3mZF7OcyUA== - -"@octokit/webhooks-types@6.7.0": - version "6.7.0" - resolved "https://registry.yarnpkg.com/@octokit/webhooks-types/-/webhooks-types-6.7.0.tgz#5fae3f6d92befcb8224a8c19a18d9d90e59f095d" - integrity sha512-bykm7UkSnxmb2uhSfcLM1Pity/LQ6ZBSdzy9HU0vXjR+2g+tzlmRhXb7Go8oj0TlgO+vDrTivGXju6zkzOGKjA== - -"@octokit/webhooks@^10.4.0": - version "10.4.0" - resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-10.4.0.tgz#b844a3a220690b0d104488e8f1229289d5169239" - integrity sha512-BZYBRB8zUm8QJOkpmmg2VWzHq21qVW6vzmZw7gXhoPp/fia1N+HKF/caWyCcKpSE4DYBnPukJ9HtpMcC2GZiRw== - dependencies: - "@octokit/request-error" "^3.0.0" - "@octokit/webhooks-methods" "^3.0.0" - "@octokit/webhooks-types" "6.7.0" - aggregate-error "^3.1.0" - -"@sinclair/typebox@^0.24.1": - version "0.24.20" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.20.tgz#11a657875de6008622d53f56e063a6347c51a6dd" - integrity sha512-kVaO5aEFZb33nPMTZBxiPEkY+slxiPtqC7QX8f9B3eGOMBvEfuMfxp9DSTTCsRJPumPKjrge4yagyssO4q6qzQ== - -"@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^9.1.2": - version "9.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" - integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== - dependencies: - "@sinonjs/commons" "^1.7.0" - -"@trivago/prettier-plugin-sort-imports@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.0.0.tgz#e0936d87fb8d65865c857e6a6dba644103db1b30" - integrity sha512-Tyuk5ZY4a0e2MNFLdluQO9F6d1awFQYXVVujEPFfvKPPXz8DADNHzz73NMhwCSXGSuGGZcA/rKOyZBrxVNMxaA== - dependencies: - "@babel/core" "7.17.8" - "@babel/generator" "7.17.7" - "@babel/parser" "7.18.9" - "@babel/traverse" "7.17.3" - "@babel/types" "7.17.0" - javascript-natural-sort "0.7.1" - lodash "4.17.21" - -"@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== - -"@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== - -"@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== - -"@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== - -"@types/aws-lambda@^8.10.109": - version "8.10.109" - resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.109.tgz#2f434cbfafe083529e365fe9c114787827a169a8" - integrity sha512-/ME92FneNyXQzrAfcnQQlW1XkCZGPDlpi2ao1MJwecN+6SbeonKeggU8eybv1DfKli90FAVT1MlIZVXfwVuCyg== - -"@types/babel__core@^7.1.14": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.16.tgz#bc12c74b7d65e82d29876b5d0baf5c625ac58702" - integrity sha512-EAEHtisTMM+KaKwfWdC3oyllIqswlznXCIVCt7/oRNrh+DhgT4UEBNC/jlADNjvw7UnfbcdkGQcPVZ1xYiLcrQ== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.3.tgz#f456b4b2ce79137f768aa130d2423d2f0ccfaba5" - integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" - integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== - dependencies: - "@babel/types" "^7.3.0" - -"@types/body-parser@*": - version "1.19.1" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.1.tgz#0c0174c42a7d017b818303d4b5d969cb0b75929c" - integrity sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg== - dependencies: - "@types/connect" "*" - "@types/node" "*" - -"@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== - dependencies: - "@types/node" "*" - -"@types/express-serve-static-core@^4.17.31": - version "4.17.31" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" - integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express@^4.17.15": - version "4.17.15" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.15.tgz#9290e983ec8b054b65a5abccb610411953d417ff" - integrity sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.31" - "@types/qs" "*" - "@types/serve-static" "*" - -"@types/graceful-fs@^4.1.3": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== - -"@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^29.2.4": - version "29.2.4" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.2.4.tgz#9c155c4b81c9570dbd183eb8604aa0ae80ba5a5b" - integrity sha512-PipFB04k2qTRPePduVLTRiPzQfvMeLwUN3Z21hsAKaB/W9IIzgB2pizCL466ftJlcyZqnHoC9ZHpxLGl3fS86A== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - -"@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== - -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== - -"@types/node@*": - version "18.11.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.12.tgz#89e7f8aa8c88abf432f9bd594888144d7dba10aa" - integrity sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg== - -"@types/node@^18.11.18": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== - -"@types/prettier@^2.1.5": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.1.tgz#e1303048d5389563e130f5bdd89d37a99acb75eb" - integrity sha512-Fo79ojj3vdEZOHg3wR9ksAMRz4P3S5fDB5e/YWZiFnyFQI1WY2Vftu9XoXVVtJfxB7Bpce/QTqWSSntkz2Znrw== - -"@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== - -"@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== - -"@types/semver@^7.3.12": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== - -"@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== - dependencies: - "@types/mime" "^1" - "@types/node" "*" - -"@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== - -"@types/strip-bom@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" - integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= - -"@types/strip-json-comments@0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" - integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== - -"@types/yargs-parser@*": - version "20.2.1" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" - integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== - -"@types/yargs@^17.0.8": - version "17.0.10" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a" - integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA== - dependencies: - "@types/yargs-parser" "*" - -"@typescript-eslint/eslint-plugin@^5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.47.1.tgz#50cc5085578a7fa22cd46a0806c2e5eae858af02" - integrity sha512-r4RZ2Jl9kcQN7K/dcOT+J7NAimbiis4sSM9spvWimsBvDegMhKLA5vri2jG19PmIPbDjPeWzfUPQ2hjEzA4Nmg== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/type-utils" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - ignore "^5.2.0" - natural-compare-lite "^1.4.0" - regexpp "^3.2.0" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/parser@^5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.47.1.tgz#c4bf16f8c3c7608ce4bf8ff804b677fc899f173f" - integrity sha512-9Vb+KIv29r6GPu4EboWOnQM7T+UjpjXvjCPhNORlgm40a9Ia9bvaPJswvtae1gip2QEeVeGh6YquqAzEgoRAlw== - dependencies: - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - debug "^4.3.4" - -"@typescript-eslint/scope-manager@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.47.1.tgz#0d302b3c2f20ab24e4787bf3f5a0d8c449b823bd" - integrity sha512-9hsFDsgUwrdOoW1D97Ewog7DYSHaq4WKuNs0LHF9RiCmqB0Z+XRR4Pf7u7u9z/8CciHuJ6yxNws1XznI3ddjEw== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - -"@typescript-eslint/type-utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.47.1.tgz#aee13314f840ab336c1adb49a300856fd16d04ce" - integrity sha512-/UKOeo8ee80A7/GJA427oIrBi/Gd4osk/3auBUg4Rn9EahFpevVV1mUK8hjyQD5lHPqX397x6CwOk5WGh1E/1w== - dependencies: - "@typescript-eslint/typescript-estree" "5.47.1" - "@typescript-eslint/utils" "5.47.1" - debug "^4.3.4" - tsutils "^3.21.0" - -"@typescript-eslint/types@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.47.1.tgz#459f07428aec5a8c4113706293c2ae876741ac8e" - integrity sha512-CmALY9YWXEpwuu6377ybJBZdtSAnzXLSQcxLSqSQSbC7VfpMu/HLVdrnVJj7ycI138EHqocW02LPJErE35cE9A== - -"@typescript-eslint/typescript-estree@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.47.1.tgz#b9d8441308aca53df7f69b2c67a887b82c9ed418" - integrity sha512-4+ZhFSuISAvRi2xUszEj0xXbNTHceV9GbH9S8oAD2a/F9SW57aJNQVOCxG8GPfSWH/X4eOPdMEU2jYVuWKEpWA== - dependencies: - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/visitor-keys" "5.47.1" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.3.7" - tsutils "^3.21.0" - -"@typescript-eslint/utils@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.47.1.tgz#595f25ac06e9ee28c339fd43c709402820b13d7b" - integrity sha512-l90SdwqfmkuIVaREZ2ykEfCezepCLxzWMo5gVfcJsJCaT4jHT+QjgSkYhs5BMQmWqE9k3AtIfk4g211z/sTMVw== - dependencies: - "@types/json-schema" "^7.0.9" - "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.47.1" - "@typescript-eslint/types" "5.47.1" - "@typescript-eslint/typescript-estree" "5.47.1" - eslint-scope "^5.1.1" - eslint-utils "^3.0.0" - semver "^7.3.7" - -"@typescript-eslint/visitor-keys@5.47.1": - version "5.47.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.47.1.tgz#d35c2da544dbb685db9c5b5b85adac0a1d74d1f2" - integrity sha512-rF3pmut2JCCjh6BLRhNKdYjULMb1brvoaiWDlHfLNVgmnZ0sBVJrs3SyaKE1XoDDnJuAx/hDQryHYmPUuNq0ig== - dependencies: - "@typescript-eslint/types" "5.47.1" - eslint-visitor-keys "^3.3.0" - -"@vercel/ncc@0.36.0": - version "0.36.0" - resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.36.0.tgz#1f262b86fc4f0770bbc0fc1d331d5aaa1bd47334" - integrity sha512-/ZTUJ/ZkRt694k7KJNimgmHjtQcRuVwsST2Z6XfYveQIuBbHR+EqkTc1jfgPkQmMyk/vtpxo3nVxe8CNuau86A== - -accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-jsx@^5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - -acorn@^8.4.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" - integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== - -acorn@^8.8.0: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== - -aggregate-error@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.10.0, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.0, ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -aws-lambda@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/aws-lambda/-/aws-lambda-1.0.7.tgz#c6b674df47458b5ecd43ab734899ad2e2d457013" - integrity sha512-9GNFMRrEMG5y3Jvv+V4azWvc+qNWdWLTjDdhf/zgMlz8haaaLWv0xeAIWxz9PuWUBawsVxy0zZotjCdR3Xq+2w== - dependencies: - aws-sdk "^2.814.0" - commander "^3.0.2" - js-yaml "^3.14.1" - watchpack "^2.0.0-beta.10" - -aws-sdk@^2.1283.0: - version "2.1283.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1283.0.tgz#87dafacd3e4c9dd89f5de0bce43cafb50fd5c9e4" - integrity sha512-YlxTF0T9X8AcNrOzFPVOPnX1jNtHZjYHRUCfpsVwqdajHDGGruVsVppgBYXEiCRuTQNUhcJTUx0J0uKBhKQZIA== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.4.19" - -aws-sdk@^2.814.0: - version "2.1271.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1271.0.tgz#a060fe65ff33afddb7385913200df4a26717f691" - integrity sha512-hQF+mjwe2FXFKOMNQGlfqn9InIL1bRp650ftctRqDo+VpnrYnKqF9eZa5Hk2kugs3/WUa4J2aqQa+foGWeH+Fg== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.4.19" - -babel-jest@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.3.1.tgz#05c83e0d128cd48c453eea851482a38782249f44" - integrity sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA== - dependencies: - "@jest/transform" "^29.3.1" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.2.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz#23ee99c37390a98cfddf3ef4a78674180d823094" - integrity sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz#3048bea3a1af222e3505e4a767a974c95a7620dc" - integrity sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA== - dependencies: - babel-plugin-jest-hoist "^29.2.0" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -base64-js@^1.0.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - -before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -body-parser@1.20.1, body-parser@^1.20.0: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - -bowser@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" - integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.20.2: - version "4.21.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf" - integrity sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA== - dependencies: - caniuse-lite "^1.0.30001366" - electron-to-chromium "^1.4.188" - node-releases "^2.0.6" - update-browserslist-db "^1.0.4" - -browserslist@^4.21.3: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== - dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" - -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -buffer@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== - -caniuse-lite@^1.0.30001366: - version "1.0.30001368" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001368.tgz#c5c06381c6051cd863c45021475434e81936f713" - integrity sha512-wgfRYa9DenEomLG/SdWgQxpIyvdtH3NW8Vq+tB6AwR9e56iOIcu1im5F/wNdDf04XlKHXqIx4N8Jo0PemeBenQ== - -caniuse-lite@^1.0.30001400: - version "1.0.30001421" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001421.tgz#979993aaacff5ab72a8d0d58c28ddbcb7b4deba6" - integrity sha512-Sw4eLbgUJAEhjLs1Fa+mk45sidp1wRn5y6GtDpHGBaNJ9OCDJaVh2tIaWWUnGfuXfKf1JCBaIarak3FkVAvEeA== - -chalk@^2.0.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -ci-info@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" - integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== - -cjs-module-lexer@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" - integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== - -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -collect-v8-coverage@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" - integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -commander@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -debug@^4.3.2, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -dedent@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" - integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= - -deep-is@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== - -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -deprecation@^2.0.0, deprecation@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" - integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -diff-sequences@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" - integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== - -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dynamic-dedupe@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" - integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= - dependencies: - xtend "^4.0.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.4.188: - version "1.4.196" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.196.tgz#e18cdc5c1c2c2ebf78da237d0c374cc3b244d4cb" - integrity sha512-uxMa/Dt7PQsLBVXwH+t6JvpHJnrsYBaxWKi/J6HE+/nBtoHENhwBoNkgkm226/Kfxeg0z1eMQLBRPPKcDH8xWA== - -electron-to-chromium@^1.4.251: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0: - version "1.20.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-plugin-prettier@4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" - integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^8.30.0: - version "8.30.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.30.0.tgz#83a506125d089eef7c5b5910eeea824273a33f50" - integrity sha512-MGADB39QqYuzEGov+F/qb18r4i7DohCDOfatHaxI2iGlPuC65bwG2gxgO+7DkyL38dRFaRH7RaRAgU6JKL9rMQ== - dependencies: - "@eslint/eslintrc" "^1.4.0" - "@humanwhocodes/config-array" "^0.11.8" - "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - doctrine "^3.0.0" - escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" - find-up "^5.0.0" - glob-parent "^6.0.2" - globals "^13.19.0" - grapheme-splitter "^1.0.4" - ignore "^5.2.0" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-sdsl "^4.1.4" - js-yaml "^4.1.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" - strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" - text-table "^0.2.0" - -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== - dependencies: - acorn "^8.8.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expect@^29.0.0, expect@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.3.1.tgz#92877aad3f7deefc2e3f6430dd195b92295554a6" - integrity sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA== - dependencies: - "@jest/expect-utils" "^29.3.1" - jest-get-type "^29.2.0" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - -express@^4.18.2: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.5.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fast-xml-parser@4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.0.11.tgz#42332a9aca544520631c8919e6ea871c0185a985" - integrity sha512-4aUg3aNRR/WjQAcpceODG1C3x3lFANXRo8+1biqfieHmg9pyMt7qB4lQV/Ta6sJCTbA5vfD8fnA8S54JATiFUA== - dependencies: - strnum "^1.0.5" - -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== - dependencies: - bser "2.1.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" - integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== - -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" - integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-parent@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.1.3: - version "7.1.7" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.4: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.19.0: - version "13.19.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.19.0.tgz#7a42de8e6ad4f7242fbcca27ea5b23aca367b5c8" - integrity sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -graceful-fs@^4.1.2: - version "4.2.6" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" - integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== - -graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ieee754@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - -ignore@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c" - integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - -is-core-module@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.5.0.tgz#f754843617c70bfd29b7bd87327400cda5c18491" - integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - -is-glob@^4.0.0, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-glob@^4.0.1, is-glob@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" - integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" - for-each "^0.3.3" - has-tostringtag "^1.0.0" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -istanbul-lib-coverage@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz#e8900b3ed6069759229cf30f7067388d148aeb5e" - integrity sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ== - -istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" - integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.3.tgz#4bcae3103b94518117930d51283690960b50d3c2" - integrity sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -javascript-natural-sort@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" - integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= - -jest-changed-files@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289" - integrity sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA== - dependencies: - execa "^5.0.0" - p-limit "^3.1.0" - -jest-circus@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.3.1.tgz#177d07c5c0beae8ef2937a67de68f1e17bbf1b4a" - integrity sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - p-limit "^3.1.0" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.3.1.tgz#e89dff427db3b1df50cea9a393ebd8640790416d" - integrity sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ== - dependencies: - "@jest/core" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-config@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.3.1.tgz#0bc3dcb0959ff8662957f1259947aedaefb7f3c6" - integrity sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.3.1" - "@jest/types" "^29.3.1" - babel-jest "^29.3.1" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.3.1" - jest-environment-node "^29.3.1" - jest-get-type "^29.2.0" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-runner "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" - integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-docblock@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" - integrity sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.3.1.tgz#bc375c8734f1bb96625d83d1ca03ef508379e132" - integrity sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA== - dependencies: - "@jest/types" "^29.3.1" - chalk "^4.0.0" - jest-get-type "^29.2.0" - jest-util "^29.3.1" - pretty-format "^29.3.1" - -jest-environment-node@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.3.1.tgz#5023b32472b3fba91db5c799a0d5624ad4803e74" - integrity sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -jest-get-type@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" - integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== - -jest-haste-map@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.3.1.tgz#af83b4347f1dae5ee8c2fb57368dc0bb3e5af843" - integrity sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A== - dependencies: - "@jest/types" "^29.3.1" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - jest-worker "^29.3.1" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz#95336d020170671db0ee166b75cd8ef647265518" - integrity sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA== - dependencies: - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-matcher-utils@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572" - integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ== - dependencies: - chalk "^4.0.0" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-message-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" - integrity sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.3.1" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.3.1.tgz#60287d92e5010979d01f218c6b215b688e0f313e" - integrity sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-util "^29.3.1" - -jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== - -jest-regex-util@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" - integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== - -jest-resolve-dependencies@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz#a6a329708a128e68d67c49f38678a4a4a914c3bf" - integrity sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA== - dependencies: - jest-regex-util "^29.2.0" - jest-snapshot "^29.3.1" - -jest-resolve@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.3.1.tgz#9a4b6b65387a3141e4a40815535c7f196f1a68a7" - integrity sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-pnp-resolver "^1.2.2" - jest-util "^29.3.1" - jest-validate "^29.3.1" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" - -jest-runner@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.3.1.tgz#a92a879a47dd096fea46bb1517b0a99418ee9e2d" - integrity sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA== - dependencies: - "@jest/console" "^29.3.1" - "@jest/environment" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.2.0" - jest-environment-node "^29.3.1" - jest-haste-map "^29.3.1" - jest-leak-detector "^29.3.1" - jest-message-util "^29.3.1" - jest-resolve "^29.3.1" - jest-runtime "^29.3.1" - jest-util "^29.3.1" - jest-watcher "^29.3.1" - jest-worker "^29.3.1" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.3.1.tgz#21efccb1a66911d6d8591276a6182f520b86737a" - integrity sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/globals" "^29.3.1" - "@jest/source-map" "^29.2.0" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.3.1.tgz#17bcef71a453adc059a18a32ccbd594b8cc4e45e" - integrity sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.3.1" - graceful-fs "^4.2.9" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - jest-haste-map "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - natural-compare "^1.4.0" - pretty-format "^29.3.1" - semver "^7.3.5" - -jest-util@^29.0.0, jest-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" - integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.3.1.tgz#d56fefaa2e7d1fde3ecdc973c7f7f8f25eea704a" - integrity sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g== - dependencies: - "@jest/types" "^29.3.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.2.0" - leven "^3.1.0" - pretty-format "^29.3.1" - -jest-watcher@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.3.1.tgz#3341547e14fe3c0f79f9c3a4c62dbc3fc977fd4a" - integrity sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg== - dependencies: - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.3.1" - string-length "^4.0.1" - -jest-worker@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" - integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== - dependencies: - "@types/node" "*" - jest-util "^29.3.1" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.3: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.3.1.tgz#c130c0d551ae6b5459b8963747fed392ddbde122" - integrity sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA== - dependencies: - "@jest/core" "^29.3.1" - "@jest/types" "^29.3.1" - import-local "^3.0.2" - jest-cli "^29.3.1" - -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - -js-sdsl@^4.1.4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" - integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ== - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1, js-yaml@^3.14.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash@4.17.21, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -make-error@1.x, make-error@^1.1.1: - version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" - integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== - dependencies: - braces "^3.0.1" - picomatch "^2.2.3" - -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.49.0.tgz#f3dfde60c99e9cf3bc9701d687778f537001cbed" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== - -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-types@~2.1.24: - version "2.1.32" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== - dependencies: - mime-db "1.49.0" - -mime-types@~2.1.34: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== - dependencies: - mime-db "1.51.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.5, minimist@^1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -natural-compare-lite@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" - integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -nock@^13.2.9: - version "13.2.9" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.2.9.tgz#4faf6c28175d36044da4cfa68e33e5a15086ad4c" - integrity sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.21" - propagate "^2.0.0" - -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - 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" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-inspect@^1.12.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -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= - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -pirates@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" - integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.1.tgz#4e1fd11c34e2421bc1da9aea9bd8127cd0a35efc" - integrity sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg== - -pretty-format@^29.0.0, pretty-format@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" - integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== - dependencies: - "@jest/schemas" "^29.0.0" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -prompts@^2.0.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61" - integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -propagate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" - integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== - -resolve@^1.0.0, resolve@^1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^2.6.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@5.2.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha1-e45lYZCyKOgaZq6nSEgNgozS03o= - -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@7.x, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== - dependencies: - lru-cache "^6.0.0" - -semver@^6.0.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.7: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== - -signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@^0.5.12, source-map-support@^0.5.21: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== - dependencies: - escape-string-regexp "^2.0.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-width@^4.1.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -ts-jest@^29.0.3: - version "29.0.3" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.3.tgz#63ea93c5401ab73595440733cefdba31fcf9cb77" - integrity sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.1" - lodash.memoize "4.x" - make-error "1.x" - semver "7.x" - yargs-parser "^21.0.1" - -ts-node-dev@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" - integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== - dependencies: - chokidar "^3.5.1" - dynamic-dedupe "^0.3.0" - minimist "^1.2.6" - mkdirp "^1.0.4" - resolve "^1.0.0" - rimraf "^2.6.1" - source-map-support "^0.5.12" - tree-kill "^1.2.2" - ts-node "^10.4.0" - tsconfig "^7.0.0" - -ts-node@^10.4.0: - version "10.8.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.1.tgz#ea2bd3459011b52699d7e88daa55a45a1af4f066" - integrity sha512-Wwsnao4DQoJsN034wePSg5nZiw4YKXf56mPIAeD6wVmiv+RytNSWqc2f3fKvcUoV+Yn2+yocD71VOfQHbmVX4g== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfig@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" - integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== - dependencies: - "@types/strip-bom" "^3.0.0" - "@types/strip-json-comments" "0.0.30" - strip-bom "^3.0.0" - strip-json-comments "^2.0.0" - -tslib@^1.11.1, tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.3.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -tslog@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.3.4.tgz#083197a908c97b3b714a0576b9dac293f223f368" - integrity sha512-N0HHuHE0e/o75ALfkioFObknHR5dVchUad4F0XyFf3gXJYB++DewEzwGI/uIOM216E5a43ovnRNEeQIq9qgm4Q== - dependencies: - source-map-support "^0.5.21" - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typescript@^4.9.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -update-browserslist-db@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38" - integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -update-browserslist-db@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -util@^0.12.4: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache-lib@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" - integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== - -v8-to-istanbul@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" - integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -watchpack@^2.0.0-beta.10: - version "2.2.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" - integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" - integrity sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-abstract "^1.20.0" - for-each "^0.3.3" - has-tostringtag "^1.0.0" - is-typed-array "^1.1.9" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.0.0, yargs-parser@^21.0.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.6.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.0.tgz#e134900fc1f218bc230192bdec06a0a5f973e46c" - integrity sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.0.0" - -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/modules/webhook/main.tf b/modules/webhook/main.tf index 01e6387682..777972f826 100644 --- a/modules/webhook/main.tf +++ b/modules/webhook/main.tf @@ -1,7 +1,7 @@ locals { webhook_endpoint = "webhook" role_path = var.role_path == null ? "/${var.prefix}/" : var.role_path - lambda_zip = var.lambda_zip == null ? "${path.module}/lambdas/webhook/webhook.zip" : var.lambda_zip + lambda_zip = var.lambda_zip == null ? "${path.module}/../../lambdas/functions/webhook/webhook.zip" : var.lambda_zip } resource "aws_apigatewayv2_api" "webhook" { @@ -19,9 +19,9 @@ resource "aws_apigatewayv2_route" "webhook" { resource "aws_apigatewayv2_stage" "webhook" { lifecycle { ignore_changes = [ - // see bug https://github.com/terraform-providers/terraform-provider-aws/issues/12893 + # see bug https://github.com/terraform-providers/terraform-provider-aws/issues/12893 default_route_settings, - // not terraform managed + # not terraform managed deployment_id ] } @@ -42,7 +42,7 @@ resource "aws_apigatewayv2_stage" "webhook" { resource "aws_apigatewayv2_integration" "webhook" { lifecycle { ignore_changes = [ - // not terraform managed + # not terraform managed passthrough_behavior ] } @@ -55,3 +55,11 @@ resource "aws_apigatewayv2_integration" "webhook" { integration_method = "POST" integration_uri = aws_lambda_function.webhook.invoke_arn } + + +resource "aws_ssm_parameter" "runner_matcher_config" { + name = "${var.ssm_paths.root}/${var.ssm_paths.webhook}/runner-matcher-config" + type = "String" + value = jsonencode(local.runner_matcher_config_sorted) + tier = var.matcher_config_parameter_store_tier +} diff --git a/modules/webhook/outputs.tf b/modules/webhook/outputs.tf index 784885a1f7..f368c0448c 100644 --- a/modules/webhook/outputs.tf +++ b/modules/webhook/outputs.tf @@ -6,6 +6,10 @@ output "lambda" { value = aws_lambda_function.webhook } +output "lambda_log_group" { + value = aws_cloudwatch_log_group.webhook +} + output "role" { value = aws_iam_role.webhook_lambda } diff --git a/modules/webhook/policies.tf b/modules/webhook/policies.tf index e69de29bb2..454d943b4b 100644 --- a/modules/webhook/policies.tf +++ b/modules/webhook/policies.tf @@ -0,0 +1,16 @@ +data "aws_iam_policy_document" "lambda_xray" { + count = var.tracing_config.mode != null ? 1 : 0 + statement { + actions = [ + "xray:BatchGetTraces", + "xray:GetTraceSummaries", + "xray:PutTelemetryRecords", + "xray:PutTraceSegments" + ] + effect = "Allow" + resources = [ + "*" + ] + sid = "AllowXRay" + } +} diff --git a/modules/webhook/policies/lambda-publish-sqs-policy.json b/modules/webhook/policies/lambda-publish-sqs-policy.json index 84de5ee3f9..6878ea125d 100644 --- a/modules/webhook/policies/lambda-publish-sqs-policy.json +++ b/modules/webhook/policies/lambda-publish-sqs-policy.json @@ -4,7 +4,17 @@ { "Effect": "Allow", "Action": ["sqs:SendMessage", "sqs:GetQueueAttributes"], - "Resource": "${sqs_resource_arn}" + "Resource": ${sqs_resource_arns} + %{ if kms_key_arn != "" ~} + }, + { + "Effect": "Allow", + "Action": [ + "kms:Decrypt", + "kms:GenerateDataKey" + ], + "Resource": "${kms_key_arn}" + %{ endif ~} } ] } diff --git a/modules/webhook/policies/lambda-ssm.json b/modules/webhook/policies/lambda-ssm.json index c635ca6398..23864db305 100644 --- a/modules/webhook/policies/lambda-ssm.json +++ b/modules/webhook/policies/lambda-ssm.json @@ -2,22 +2,12 @@ "Version": "2012-10-17", "Statement": [ { - "Effect": "Allow", - "Action": [ - "ssm:GetParameter" - ], - "Resource": [ - "${github_app_webhook_secret_arn}" - ] - %{ if kms_key_arn != "" ~} - }, - { - "Effect": "Allow", - "Action": [ - "kms:Decrypt" - ], - "Resource": "${kms_key_arn}" - %{ endif ~} + "Effect": "Allow", + "Action": ["ssm:GetParameter"], + "Resource": [ + "${github_app_webhook_secret_arn}", + "${parameter_runner_matcher_config_arn}" + ] } ] } diff --git a/modules/webhook/variables.tf b/modules/webhook/variables.tf index de26bb8b5a..f427fa3412 100644 --- a/modules/webhook/variables.tf +++ b/modules/webhook/variables.tf @@ -1,17 +1,13 @@ -variable "aws_region" { - description = "AWS region." - type = string +variable "lambda_subnet_ids" { + description = "List of subnets in which the action runners will be launched, the subnets needs to be subnets in the `vpc_id`." + type = list(string) + default = [] } -variable "environment" { - description = "A name that identifies the environment, used as prefix and for tagging." - type = string - default = null - - validation { - condition = var.environment == null - error_message = "The \"environment\" variable is no longer used. To migrate, set the \"prefix\" variable to the original value of \"environment\" and optionally, add \"Environment\" to the \"tags\" variable map with the same value." - } +variable "lambda_security_group_ids" { + description = "List of security group IDs associated with the Lambda function." + type = list(string) + default = [] } variable "prefix" { @@ -20,23 +16,30 @@ variable "prefix" { default = "github-actions" } -variable "github_app_webhook_secret_arn" { - type = string -} - variable "tags" { description = "Map of tags that will be added to created resources. By default resources will be tagged with name and environment." type = map(string) default = {} } -variable "sqs_build_queue" { - description = "SQS queue to publish accepted build events." - type = object({ - id = string - arn = string - }) +variable "runner_matcher_config" { + description = "SQS queue to publish accepted build events based on the runner type. When exact match is disabled the webhook accepts the event if one of the workflow job labels is part of the matcher. The priority defines the order the matchers are applied." + type = map(object({ + arn = string + id = string + fifo = bool + matcherConfig = object({ + labelMatchers = list(list(string)) + exactMatch = bool + priority = optional(number, 999) + }) + })) + validation { + condition = try(var.runner_matcher_config.matcherConfig.priority, 999) >= 0 && try(var.runner_matcher_config.matcherConfig.priority, 999) < 1000 + error_message = "The priority of the matcher must be between 0 and 999." + } } + variable "sqs_workflow_job_queue" { description = "SQS queue to monitor github events." type = object({ @@ -51,6 +54,12 @@ variable "lambda_zip" { default = null } +variable "lambda_memory_size" { + description = "Memory size limit in MB for lambda." + type = number + default = 256 +} + variable "lambda_timeout" { description = "Time out of the lambda in seconds." type = number @@ -72,7 +81,7 @@ variable "role_path" { variable "logging_retention_in_days" { description = "Specifies the number of days you want to retain log events for the lambda log group. Possible values are: 0, 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653." type = number - default = 7 + default = 180 } variable "logging_kms_key_id" { @@ -83,16 +92,19 @@ variable "logging_kms_key_id" { variable "lambda_s3_bucket" { description = "S3 bucket from which to specify lambda functions. This is an alternative to providing local files directly." + type = string default = null } variable "webhook_lambda_s3_key" { description = "S3 key for webhook lambda function. Required if using S3 bucket to specify lambdas." + type = string default = null } variable "webhook_lambda_s3_object_version" { description = "S3 object version for webhook lambda function. Useful if S3 versioning is enabled on source bucket." + type = string default = null } @@ -106,7 +118,7 @@ variable "webhook_lambda_apigateway_access_log_settings" { } variable "repository_white_list" { - description = "List of repositories allowed to use the github app" + description = "List of github repository full names (owner/repo_name) that will be allowed to use the github app. Leave empty for no filtering." type = list(string) default = [] } @@ -117,80 +129,84 @@ variable "kms_key_arn" { default = null } -variable "runner_labels" { - description = "Extra (custom) labels for the runners (GitHub). Separate each label by a comma. Labels checks on the webhook can be enforced by setting `enable_workflow_job_labels_check`. GitHub read-only labels should not be provided." - type = string - default = "" -} - -variable "enable_workflow_job_labels_check" { - description = "If set to true all labels in the workflow job even are matched against the custom labels and GitHub labels (os, architecture and `self-hosted`). When the labels are not matching the event is dropped at the webhook." - type = bool - default = false -} - -variable "workflow_job_labels_check_all" { - description = "If set to true all labels in the workflow job must match the GitHub labels (os, architecture and `self-hosted`). When false if __any__ label matches it will trigger the webhook. `enable_workflow_job_labels_check` must be true for this to take effect." - type = bool - default = true -} - -variable "log_type" { - description = "Logging format for lambda logging. Valid values are 'json', 'pretty', 'hidden'. " - type = string - default = "pretty" - validation { - condition = anytrue([ - var.log_type == "json", - var.log_type == "pretty", - var.log_type == "hidden", - ]) - error_message = "`log_type` value not valid. Valid values are 'json', 'pretty', 'hidden'." - } -} - variable "log_level" { description = "Logging level for lambda logging. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." type = string default = "info" validation { condition = anytrue([ - var.log_level == "silly", - var.log_level == "trace", var.log_level == "debug", var.log_level == "info", var.log_level == "warn", var.log_level == "error", - var.log_level == "fatal", ]) - error_message = "`log_level` value not valid. Valid values are 'silly', 'trace', 'debug', 'info', 'warn', 'error', 'fatal'." + error_message = "`log_level` value not valid. Valid values are 'debug', 'info', 'warn', 'error'." + } + validation { + condition = !contains(["silly", "trace", "fatal"], var.log_level) + error_message = "PLEASE MIGRATE: The following log levels: 'silly', 'trace' and 'fatal' are not longer supported." } -} - -variable "disable_check_wokflow_job_labels" { - description = "Disable the check of workflow labels." - type = bool - default = false -} - -variable "sqs_build_queue_fifo" { - description = "Enable a FIFO queue to remain the order of events received by the webhook. Suggest to set to true for repo level runners." - type = bool - default = false } variable "lambda_runtime" { description = "AWS Lambda runtime." type = string - default = "nodejs16.x" + default = "nodejs20.x" +} + +variable "aws_partition" { + description = "(optional) partition for the base arn if not 'aws'" + type = string + default = "aws" } variable "lambda_architecture" { description = "AWS Lambda architecture. Lambda functions using Graviton processors ('arm64') tend to have better price/performance than 'x86_64' functions. " type = string - default = "x86_64" + default = "arm64" validation { condition = contains(["arm64", "x86_64"], var.lambda_architecture) error_message = "`lambda_architecture` value is not valid, valid values are: `arm64` and `x86_64`." } } + +variable "github_app_parameters" { + description = "Parameter Store for GitHub App Parameters." + type = object({ + webhook_secret = map(string) + }) +} + +variable "tracing_config" { + description = "Configuration for lambda tracing." + type = object({ + mode = optional(string, null) + capture_http_requests = optional(bool, false) + capture_error = optional(bool, false) + }) + default = {} +} + +variable "ssm_paths" { + description = "The root path used in SSM to store configuration and secrets." + type = object({ + root = string + webhook = string + }) +} + +variable "lambda_tags" { + description = "Map of tags that will be added to all the lambda function resources. Note these are additional tags to the default tags." + type = map(string) + default = {} +} + +variable "matcher_config_parameter_store_tier" { + description = "The tier of the parameter store for the matcher configuration. Valid values are `Standard`, and `Advanced`." + type = string + default = "Standard" + validation { + condition = contains(["Standard", "Advanced"], var.matcher_config_parameter_store_tier) + error_message = "`matcher_config_parameter_store_tier` value is not valid, valid values are: `Standard`, and `Advanced`." + } +} diff --git a/modules/webhook/versions.tf b/modules/webhook/versions.tf index ac1bb9a5d5..d780c7775c 100644 --- a/modules/webhook/versions.tf +++ b/modules/webhook/versions.tf @@ -1,10 +1,15 @@ terraform { - required_version = ">= 0.14.1" + required_version = ">= 1.3.0" required_providers { aws = { source = "hashicorp/aws" - version = "~> 4.0" + version = "~> 5.27" + } + + null = { + source = "hashicorp/null" + version = "~> 3.2" } } } diff --git a/modules/webhook/webhook.tf b/modules/webhook/webhook.tf index 8e001515e7..5c5759b51b 100644 --- a/modules/webhook/webhook.tf +++ b/modules/webhook/webhook.tf @@ -1,3 +1,12 @@ +locals { + # config with combined key and order + runner_matcher_config = { for k, v in var.runner_matcher_config : format("%03d-%s", v.matcherConfig.priority, k) => merge(v, { key = k }) } + + # sorted list + runner_matcher_config_sorted = [for k in sort(keys(local.runner_matcher_config)) : local.runner_matcher_config[k]] +} + + resource "aws_lambda_function" "webhook" { s3_bucket = var.lambda_s3_bucket != null ? var.lambda_s3_bucket : null s3_key = var.webhook_lambda_s3_key != null ? var.webhook_lambda_s3_key : null @@ -8,25 +17,45 @@ resource "aws_lambda_function" "webhook" { role = aws_iam_role.webhook_lambda.arn handler = "index.githubWebhook" runtime = var.lambda_runtime + memory_size = var.lambda_memory_size timeout = var.lambda_timeout architectures = [var.lambda_architecture] environment { variables = { - ENABLE_WORKFLOW_JOB_LABELS_CHECK = var.enable_workflow_job_labels_check - WORKFLOW_JOB_LABELS_CHECK_ALL = var.workflow_job_labels_check_all - ENVIRONMENT = var.prefix - LOG_LEVEL = var.log_level - LOG_TYPE = var.log_type - REPOSITORY_WHITE_LIST = jsonencode(var.repository_white_list) - RUNNER_LABELS = jsonencode(split(",", lower(var.runner_labels))) - SQS_URL_WEBHOOK = var.sqs_build_queue.id - SQS_IS_FIFO = var.sqs_build_queue_fifo - SQS_WORKFLOW_JOB_QUEUE = try(var.sqs_workflow_job_queue, null) != null ? var.sqs_workflow_job_queue.id : "" + for k, v in { + LOG_LEVEL = var.log_level + POWERTOOLS_LOGGER_LOG_EVENT = var.log_level == "debug" ? "true" : "false" + POWERTOOLS_TRACE_ENABLED = var.tracing_config.mode != null ? true : false + POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS = var.tracing_config.capture_http_requests + POWERTOOLS_TRACER_CAPTURE_ERROR = var.tracing_config.capture_error + PARAMETER_GITHUB_APP_WEBHOOK_SECRET = var.github_app_parameters.webhook_secret.name + REPOSITORY_ALLOW_LIST = jsonencode(var.repository_white_list) + SQS_WORKFLOW_JOB_QUEUE = try(var.sqs_workflow_job_queue.id, null) + PARAMETER_RUNNER_MATCHER_CONFIG_PATH = aws_ssm_parameter.runner_matcher_config.name + } : k => v if v != null + } + } + + dynamic "vpc_config" { + for_each = var.lambda_subnet_ids != null && var.lambda_security_group_ids != null ? [true] : [] + content { + security_group_ids = var.lambda_security_group_ids + subnet_ids = var.lambda_subnet_ids } } - tags = var.tags + tags = merge(var.tags, var.lambda_tags) + + dynamic "tracing_config" { + for_each = var.tracing_config.mode != null ? [true] : [] + content { + mode = var.tracing_config.mode + } + } + lifecycle { + replace_triggered_by = [aws_ssm_parameter.runner_matcher_config, null_resource.github_app_parameters] + } } resource "aws_cloudwatch_log_group" "webhook" { @@ -42,6 +71,15 @@ resource "aws_lambda_permission" "webhook" { function_name = aws_lambda_function.webhook.function_name principal = "apigateway.amazonaws.com" source_arn = "${aws_apigatewayv2_api.webhook.execution_arn}/*/*/${local.webhook_endpoint}" + lifecycle { + replace_triggered_by = [aws_ssm_parameter.runner_matcher_config, null_resource.github_app_parameters] + } +} + +resource "null_resource" "github_app_parameters" { + triggers = { + github_app_webhook_secret = var.github_app_parameters.webhook_secret.name + } } data "aws_iam_policy_document" "lambda_assume_role_policy" { @@ -71,12 +109,19 @@ resource "aws_iam_role_policy" "webhook_logging" { }) } +resource "aws_iam_role_policy_attachment" "webhook_vpc_execution_role" { + count = length(var.lambda_subnet_ids) > 0 ? 1 : 0 + role = aws_iam_role.webhook_lambda.name + policy_arn = "arn:${var.aws_partition}:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" +} + resource "aws_iam_role_policy" "webhook_sqs" { name = "${var.prefix}-lambda-webhook-publish-sqs-policy" role = aws_iam_role.webhook_lambda.name policy = templatefile("${path.module}/policies/lambda-publish-sqs-policy.json", { - sqs_resource_arn = var.sqs_build_queue.arn + sqs_resource_arns = jsonencode([for k, v in var.runner_matcher_config : v.arn]) + kms_key_arn = var.kms_key_arn != null ? var.kms_key_arn : "" }) } @@ -86,7 +131,8 @@ resource "aws_iam_role_policy" "webhook_workflow_job_sqs" { role = aws_iam_role.webhook_lambda.name policy = templatefile("${path.module}/policies/lambda-publish-sqs-policy.json", { - sqs_resource_arn = var.sqs_workflow_job_queue.arn + sqs_resource_arns = jsonencode([var.sqs_workflow_job_queue.arn]) + kms_key_arn = var.kms_key_arn != null ? var.kms_key_arn : "" }) } @@ -95,7 +141,13 @@ resource "aws_iam_role_policy" "webhook_ssm" { role = aws_iam_role.webhook_lambda.name policy = templatefile("${path.module}/policies/lambda-ssm.json", { - github_app_webhook_secret_arn = var.github_app_webhook_secret_arn, - kms_key_arn = var.kms_key_arn != null ? var.kms_key_arn : "" + github_app_webhook_secret_arn = var.github_app_parameters.webhook_secret.arn, + parameter_runner_matcher_config_arn = aws_ssm_parameter.runner_matcher_config.arn }) } + +resource "aws_iam_role_policy" "xray" { + count = var.tracing_config.mode != null ? 1 : 0 + policy = data.aws_iam_policy_document.lambda_xray[0].json + role = aws_iam_role.webhook_lambda.name +} diff --git a/modules/webhook/yarn.lock b/modules/webhook/yarn.lock deleted file mode 100644 index 7480029b41..0000000000 --- a/modules/webhook/yarn.lock +++ /dev/null @@ -1,28 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U= - -source-map-support@^0.5.19: - version "0.5.20" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" - integrity sha1-EhZgifj15ejFaSazd2Mzkt0stsk= - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha1-dHIq8y6WFOnCh6jQu95IteLxomM= - -tslog@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/tslog/-/tslog-3.2.2.tgz#5bbaa1fab685c4273e59b38064227321a69a0694" - integrity sha1-W7qh+raFxCc+WbOAZCJzIaaaBpQ= - dependencies: - source-map-support "^0.5.19" diff --git a/outputs.tf b/outputs.tf index 43c6985164..c8c92beac2 100644 --- a/outputs.tf +++ b/outputs.tf @@ -5,30 +5,38 @@ output "runners" { launch_template_version = module.runners.launch_template.latest_version launch_template_ami_id = module.runners.launch_template.image_id lambda_up = module.runners.lambda_scale_up + lambda_up_log_group = module.runners.lambda_scale_up_log_group lambda_down = module.runners.lambda_scale_down + lambda_down_log_group = module.runners.lambda_scale_down_log_group + lambda_pool = module.runners.lambda_pool + lambda_pool_log_group = module.runners.lambda_pool_log_group role_runner = module.runners.role_runner role_scale_up = module.runners.role_scale_up role_scale_down = module.runners.role_scale_down role_pool = module.runners.role_pool - labels = sort(split(",", local.runner_labels)) + runners_log_groups = module.runners.runners_log_groups + labels = local.runner_labels + logfiles = module.runners.logfiles } } output "binaries_syncer" { value = var.enable_runner_binaries_syncer ? { - lambda = module.runner_binaries[0].lambda - lambda_role = module.runner_binaries[0].lambda_role - location = "s3://${module.runner_binaries[0].bucket.id}/module.runner_binaries[0].bucket.key" - bucket = module.runner_binaries[0].bucket + lambda = module.runner_binaries[0].lambda + lambda_log_group = module.runner_binaries[0].lambda_log_group + lambda_role = module.runner_binaries[0].lambda_role + location = "s3://${module.runner_binaries[0].bucket.id}/module.runner_binaries[0].bucket.key" + bucket = module.runner_binaries[0].bucket } : null } output "webhook" { value = { - gateway = module.webhook.gateway - lambda = module.webhook.lambda - lambda_role = module.webhook.role - endpoint = "${module.webhook.gateway.api_endpoint}/${module.webhook.endpoint_relative_path}" + gateway = module.webhook.gateway + lambda = module.webhook.lambda + lambda_log_group = module.webhook.lambda_log_group + lambda_role = module.webhook.role + endpoint = "${module.webhook.gateway.api_endpoint}/${module.webhook.endpoint_relative_path}" } } @@ -42,6 +50,14 @@ output "queues" { value = { build_queue_arn = aws_sqs_queue.queued_builds.arn build_queue_dlq_arn = var.redrive_build_queue.enabled ? aws_sqs_queue.queued_builds_dlq[0].arn : null - webhook_workflow_job_queue = try(aws_sqs_queue.webhook_events_workflow_job_queue[0], null) != null ? aws_sqs_queue.webhook_events_workflow_job_queue[0].arn : "" + webhook_workflow_job_queue = try(aws_sqs_queue.webhook_events_workflow_job_queue[*].arn, "") } } + +output "instance_termination_watcher" { + value = var.instance_termination_watcher.enable ? { + lambda = module.instance_termination_watcher[0].lambda.function + lambda_log_group = module.instance_termination_watcher[0].lambda.log_group + lambda_role = module.instance_termination_watcher[0].lambda.role + } : null +} diff --git a/policies/lambda-publish-sqs-policy.json b/policies/lambda-publish-sqs-policy.json index 84de5ee3f9..eec8baa7eb 100644 --- a/policies/lambda-publish-sqs-policy.json +++ b/policies/lambda-publish-sqs-policy.json @@ -4,7 +4,7 @@ { "Effect": "Allow", "Action": ["sqs:SendMessage", "sqs:GetQueueAttributes"], - "Resource": "${sqs_resource_arn}" + "Resource": ${sqs_resource_arn} } ] } diff --git a/variables.ami-housekeepr.tf b/variables.ami-housekeepr.tf new file mode 100644 index 0000000000..5c7a2e5905 --- /dev/null +++ b/variables.ami-housekeepr.tf @@ -0,0 +1,70 @@ + +variable "enable_ami_housekeeper" { + description = "Option to disable the lambda to clean up old AMIs." + type = bool + default = false +} + +variable "ami_housekeeper_lambda_zip" { + description = "File location of the lambda zip file." + type = string + default = null +} + +variable "ami_housekeeper_lambda_timeout" { + description = "Time out of the lambda in seconds." + type = number + default = 300 +} + +variable "ami_housekeeper_lambda_s3_key" { + description = "S3 key for syncer lambda function. Required if using S3 bucket to specify lambdas." + type = string + default = null +} + +variable "ami_housekeeper_lambda_s3_object_version" { + description = "S3 object version for syncer lambda function. Useful if S3 versioning is enabled on source bucket." + type = string + default = null +} + +variable "ami_housekeeper_lambda_schedule_expression" { + description = "Scheduler expression for action runner binary syncer." + type = string + default = "rate(1 day)" +} + +variable "ami_housekeeper_cleanup_config" { + description = <