[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ntrim_trailing_whitespace = true\ninsert_final_newline = true\ncharset = utf-8\nindent_style = space\nindent_size = 2\nmax_line_length = 140\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[{*.sh,gradlew}]\nend_of_line = lf\n\n[{*.bat,*.cmd}]\nend_of_line = crlf\n\n[{*.kts,*.kt}]\nindent_size = 4\nij_kotlin_code_style_defaults = KOTLIN_OFFICIAL\nij_kotlin_allow_trailing_comma = true\nij_kotlin_allow_trailing_comma_on_call_site = true\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n*.sh text eol=lf\ngradlew text eol=lf\n*.bat text eol=crlf\n*.jar binary\n"
  },
  {
    "path": ".github/workflows/check-action-typing.yml",
    "content": "name: Check Action Typing\n\non:\n    push:\n      paths:\n        - 'action.yml'\n        - 'action-types.yml'\n    pull_request:\n      paths:\n        - 'action.yml'\n        - 'action-types.yml'\n\njobs:\n    check_action_typing:\n        name: Check Action Typing\n        runs-on: ubuntu-latest\n        steps:\n            - name: Checkout\n              uses: actions/checkout@v6\n\n            - name: Check Action Typing\n              uses: krzema12/github-actions-typing@v0\n"
  },
  {
    "path": ".github/workflows/gradle-wrapper-validation.yml",
    "content": "name: \"Validate Gradle Wrapper\"\non: [push, pull_request]\n\npermissions:\n  contents: read\n\njobs:\n  validation:\n    name: \"Validation\"\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: gradle/wrapper-validation-action@v3\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "# The default workflow for GitHub Actions that is used for continuous\n# integration. A configuration file that is used to control when, where,\n# and how different CI jobs are executed.\n# For more information on how to modify this file check the following link:\n# https://help.github.com/en/actions/automating-your-workflow-with-github-actions\n\nname: CI\n\non:\n  push:\n    branches:\n      - '*'\n  pull_request:\n    branches:\n      - '*'\n\njobs:\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v6\n    - name: Install Java 17\n      uses: actions/setup-java@v5\n      with:\n        java-version: 17\n        distribution: liberica\n    - uses: burrunan/gradle-cache-action@v3\n      name: Cache .gradle\n    - name: Build\n      run: ./gradlew --no-parallel --no-daemon --build-cache build\n    - name: Publish release\n      if: ${{ github.ref == 'refs/heads/main' }}\n      env:\n        PUSH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      run: |\n        git fetch origin refs/heads/release:release\n        git checkout release\n        cp cache-action-entrypoint/build/dist/js/productionExecutable/cache-action-entrypoint.js* dist/\n        git checkout main action.yml\n        git checkout main action-types.yml\n        git add dist/ action.yml action-types.yml\n        if git diff --staged --quiet; then\n          echo Everything is UP-TO-DATE\n        else\n          echo Pushing the new release\n          git fetch origin 'refs/tags/v*:refs/tags/v*'\n          if [[ $(git tag --points-at HEAD) ]] || [[ \"$(git log --format=%B -n 1 origin/release)\" != 'Publish release from'* ]]; then\n            AMEND=\n            FORCE=\n          else\n            AMEND=--amend\n            FORCE=--force\n          fi\n          git config --global user.email \"sitnikov.vladimir@gmail.com\"\n          git config --global user.name \"CI\"\n          git commit $AMEND -m \"Publish release from $GITHUB_SHA\"\n          remote_repo=\"https://${GITHUB_ACTOR}:${PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git\"\n          git push $remote_repo $FORCE release\n        fi\n"
  },
  {
    "path": ".gitignore",
    "content": "/.idea/\n/.gradle/\n/build/\n/*/build/\n/*/*/build/\n/externals/\n/*/externals/\n/*/*/externals/\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 2024-05-03: v3 🚀 Move to actions/cache@v4 API, resolve \"Cache service responded with 422\"\n* Bump to actions/cache@v4 API\n\n* Bump Gradle to 8.14\n* Bump to Kotlin 2.1.20\n* Bump kotlinx-coroutines to 1.10.2\n* Bump kotlin-serialization to 1.8.1\n* Bump kotlin-wrappers to 2025.5.2\n\n## 2024-07-25: v2, v1.21 🚀 Move to node20\n\n* Bump `node16` to `node20`. This resolves \"node16 is deprecated\" warning.\n\n* Bump Gradle to 8.8\n* Bump kotlinx-coroutines to 1.8.1\n* Bump kotlin-serialization to 1.7.1\n* Bump wrapper-validation-action to v3\n* Bump setup-java, checkout to v4\n\n## 2023-02-18: v1.21 🚑 bump dependencies\n\n* Add wrapper-validation-action\n* Bump checkout and setup-java to v3\n\n## 2023-02-18: v1.20 🚑 Avoid crash on missing layer-..json file\n\n* fix: avoid failure when index restore misses layer-..json file\n* Migrate to kotlin-wrappers:kotlin-actions-toolkit for better Kotlin wrappers https://github.com/burrunan/gradle-cache-action/pull/65\n* Bump Gradle to 8.0.1\n* Bump Kotlin to 1.8.10\n\n## 2023-02-03: v1.19 🚑 Support nested version catalogs\n\n* Also consider nested version catalogs in default dependency paths: https://github.com/burrunan/gradle-cache-action/issues/63\n\nThanks to [Vampire](https://github.com/Vampire) for the contribution.\n\n## 2023-02-03: v1.18 🚑 fix crash when git log returns a string with a newline\n\n* Trim the resulting SHA to prevent failures like in https://github.com/burrunan/gradle-cache-action/issues/63\n\n## 2023-02-03: v1.17 🚀 better types for list arguments in github-workflows-kt\n\n* Mark list arguments better: https://github.com/burrunan/gradle-cache-action/pull/61\n* Add gradle/libs.versions.toml to the default dependency paths: https://github.com/burrunan/gradle-cache-action/pull/62\n\nThanks to [Vampire](https://github.com/Vampire) for the contribution.\n\n## 2023-01-23: v1.16 🚀 added types for github-workflows-kt\n\nSee https://github.com/burrunan/gradle-cache-action/issues/58\n\nThanks to [Vampire](https://github.com/Vampire) for the contribution.\n\n## 2022-11-27: v1.15 ⬆️ bump dependencies\nIncludes all the fixes from 1.13 and 1.14.\n\n## 2022-10-29: v1.14 ⬆️ bump dependencies\n*Unreleased*: the code was not compatible with `kotlin-wrappers/node`, so it did not work. Use 1.15 instead.\n\n* bump @actions/core: 1.9.1 -> 1.10.0 (fix set-state warning)\n* bump @actions/cache: 3.0.4 -> 3.0.6\n\n## 2022-08-24: v1.13 ⬆️ bump dependencies\n*Unreleased*: the code was not compatible with `kotlin-wrappers/node`, so it did not work.  Use 1.15 instead.\n\n* bump @actions/core: 1.9.0 -> 1.9.1\n* bump @actions/cache: 3.0.0 -> 3.0.4\n* Move from kotlinx-node to kotlin-wrappers/node\n* Print stacktrace on cache proxy server failure\n* Bump Gradle to 7.5.1\n\n## 2022-07-15: v1.12 ⬆️ bump dependencies\n\n* Kotlin 1.4.31 legacy -> 1.7.10 IR\n* @actions/cache: 1.0.1 -> 3.0.0\n* @actions/core: 1.2.4 -> 1.9.0\n* @actions/exec 1.0.4 -> 1.1.1\n* @actions/glob 0.1.0 -> 0.3.0\n* @actions/http-client 1.0.8 -> 2.0.1\n* @actions/io 1.0.2 -> 1.1.2\n* @actions/tool-cache 1.6.0 -> 2.0.1\n* @octokit/request-error 2.0.2 -> 3.0.0\n* @octokit/types 5.4.0 -> 6.39.0\n* @octokit/webhooks 7.9.3 -> 10.0.8\n* nodejs: 12.18.3 -> 16.16.0\n\nThanks to https://github.com/infomiho for https://github.com/burrunan/gradle-cache-action/pull/49\n\n## 2022-07-06: v1.11 🚑 add home-directory property to override $HOME location\n\nWhen Docker executes under root user, it will use `/root` as home directory,\nso cache location would use locations like `/root/.gradle`.\n\nThe new `home-directory: /path/to/proper/user/home` property can be used to\noverride the location of `$HOME`.\n\nSee https://github.com/burrunan/gradle-cache-action/issues/41\n\n## 2021-03-09: v1.10 🚀 optimize local build cache with push=false when read-only\n\nLocal build cache won't help much in the read-only mode since workers are stateless anyway.\nDisabling the cache reduces the time it takes to pack cache entries.\n\n## 2021-03-09: v1.9 🚀 optimize remote build cache with push=false when read-only\n\nPreviously `read-only` was implemented as \"skip saving the caches\",\nhowever it makes sense to configure `push=false` so Gradle skips cache entry preparation as well.\n\n## 2021-03-09: v1.8 🚑 support Gradle 5\n\nSupport Gradle 5 (and possibly even earlier versions).\nPreviously the plugin added `init.gradle` script to activate remote build cache aggregator.\nHowever, `beforeSettings` is Gradle 6.0+ only, so in previous Gradle versions\n`gradle-cache-action` skips `com.github.burrunan.multi-cache` plugin.\n\nThe impact is old Gradle versions would not be able to use both GitHub cache and\ncustom remote build cache at the same time (only project-defined remote build cache would be used).\n\n## 2021-03-08: v1.7 🚀 support read-only cache operation\n\nThe following configuration would make all non-main branch builds to use read-only caching:\n`read-only: ${{ github.ref != 'refs/heads/main' }}`.\nIt would save GitHub space usage for PR builds, however, they would still use\ncaches from the main branch.\n\nBump Gradle: 6.5.1 -> 6.8.3\nBump Kotlin: 1.4.0-rc -> 1.4.31\nBump kotlinx-serialization: 1.0-M1-1.4.0-rc -> 1.1.0\nBump kotlinx-serialization: 1.0-M1-1.4.0-rc -> 1.1.0\nBump kotlinx-coroutines: 1.3.8-1.4.0-rc -> 1.4.3\nBump kotlin-wrappers: 1.0.1-pre.110 -> 1.0.1-pre.148\n\n## 2020-12-09: v1.6 🚀 added option to silence warnings\n\nAdd `gradle-distribution-sha-256-sum-warning` option to silence warning in case checksum is missing.\nAdd `gradle-build-scan-report` to skip publishing Gradle Build Scan URL to the job report.\n\nThanks to [Przemysław Jakubczyk](https://github.com/pjakubczyk) for the contributions.\n\n## 2020-09-24: v1.5 🚑 support branch names with slashes\n\n`feature/branch` is a valid branch name in Git, so `gradle-cache-action` now escapes `/` when\nusing branch name as a part of the cache key.\n\n## 2020-08-20: v1.4 🚑 better exclusions for *.lock files\n\nIt turns out caching action can't apply exclude if user included of the parent folders.\n\nSee https://github.com/actions/cache/issues/364#issuecomment-678118231\n\nIt should fix errors like\n\n```\nC:\\windows\\System32\\tar.exe -z -cf cache.tgz -P -C D:/a/... --files-from manifest.txt\ntar.exe: Couldn't open C:/Users/runneradmin/.gradle/caches/6.6/generated-gradle-jars/generated-gradle-jars.lock: Permission denied\ntar.exe: Error exit delayed from previous errors.\n```\n\n## 2020-08-20 🙈 silence insecure protocols warning\n\nModern Gradle versions issue a warning when users configure `http://` build cache.\nIn practice, GitHub-based cache is located on localhost, so it is fine to use http.\n\nThe plugin adds the relevant configuration to silence Gradle warning.\n\n## 2020-08-19 🚀 Unlock Gradle remote build caching\n\n* Add HTTP caching proxy that implements Gradle HTTP cache API [effb04a](https://github.com/burrunan/gradle-cache-action/commit/effb04a)\n\nThis enables Gradle to use GitHub cache API like a regular remote build cache service,\nso the caching is more efficient. Gradle fetches only the objects it needs,\nand it uploads only what was changed. Cache eviction is managed by GitHub.\n\nThe remote build cache feature activates when you use `with: arguments: build ...`\nto launch the build. In other words, you need to launch Gradle via `gradle-cache-action`\nrather that regular `run:` or `gradle-command-action`.\n\nHere's how you can integrate build cache to existing projects:\n\n* Apache Calcite: https://github.com/apache/calcite/pull/2114\n* Apache JMeter: https://github.com/apache/jmeter/pull/611\n* pgjdbc: https://github.com/pgjdbc/pgjdbc/pull/1862\n* junit-pioneer: https://github.com/junit-pioneer/junit-pioneer/pull/325\n* opentelemetry-java-instrumentation: https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/1054\n\n### Fixes\n\n* Reduce verbosity of \"cache already exists\" warning to info [8ff7dd7](https://github.com/burrunan/gradle-cache-action/commit/8ff7dd7)\n* Gradle dependencies: treat *.gradle.kts as a part of the cache key [1c59269](https://github.com/burrunan/gradle-cache-action/commit/1c59269)\n* Parse properties from properties tag rather than from arguments [140d8d9](https://github.com/burrunan/gradle-cache-action/commit/140d8d9)\n* Add wrappers [597d5ea](https://github.com/burrunan/gradle-cache-action/commit/597d5ea)\n\n## 2020-08-15 Support schedule and workflow_dispatch events\n\n* Treat workflow_dispatch event (manual launch) the same as \"build from the default branch) [48e88ce](https://github.com/burrunan/gradle-cache-action/commit/48e88ce)\n* Use defaultbranch for schedule-based builds by default [8d3e9cc](https://github.com/burrunan/gradle-cache-action/commit/8d3e9cc)\n* 🐛 Avoid build failures on schedule events: use a fixed \"defaultbranch\" instead of computing the branch name [6957760](https://github.com/burrunan/gradle-cache-action/commit/6957760)\n\n### Fixes\n\n* 🥅 Ignore unreadable files when hasing (and print warning) [01d4c8f](https://github.com/burrunan/gradle-cache-action/commit/01d4c8f)\n* 🐛 avoid adding /**/ mask to Gradle dependencies key [6d3e893](https://github.com/burrunan/gradle-cache-action/commit/6d3e893)\n* Add exception message to hashFiles(...) [d5f863c](https://github.com/burrunan/gradle-cache-action/commit/d5f863c)\n* Disable minification for better error reporting in GitHub [29d2590](https://github.com/burrunan/gradle-cache-action/commit/29d2590)\n* 🐛 Add missing await in mkdir(String) [e4a441d](https://github.com/burrunan/gradle-cache-action/commit/e4a441d)\n* 🐛 Add missing JsModule declaration [54f0245](https://github.com/burrunan/gradle-cache-action/commit/54f0245)\n* 🐛 Fix release publishing [b52aa2f](https://github.com/burrunan/gradle-cache-action/commit/b52aa2f)\n* Split modules [365cc69](https://github.com/burrunan/gradle-cache-action/commit/365cc69)\n* 🔨 Split modules [ec0c31a](https://github.com/burrunan/gradle-cache-action/commit/ec0c31a)\n* ✅ Add basic tests for cache store and restore, fix invalid \"always partial restore\" status [594213e](https://github.com/burrunan/gradle-cache-action/commit/594213e)\n* Add test for hashFilesDetailed [ce7fa0f](https://github.com/burrunan/gradle-cache-action/commit/ce7fa0f)\n\n## 2020-07-27\n\n✨ add gradle-dependencies-cache-key property for configuring extra dependencies (e.g. versions declared in buildSrc/Versions.kt) [cc7a294](https://github.com/burrunan/gradle-cache-action/commit/cc7a294)\n\n## 2020-07-27 🎉 Initial version\n\nThe following caches are saved and restored:\n* Gradle dependencies (~/.gradle/caches/modules-2)\n* Gradle local build cache (~/.gradle/caches/build-cache-1)\n* Gradle generated jars (~/.gradle/caches/*.*/generated-gradle-jars)\n* Maven local repository (~/.m2/repository)\n"
  },
  {
    "path": "LICENSE",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "NOTICE",
    "content": "Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n"
  },
  {
    "path": "README.md",
    "content": "# Gradle Cache Action\n\n[![CI Status](https://github.com/burrunan/gradle-cache-action/workflows/CI/badge.svg)](https://github.com/burrunan/gradle-cache-action/actions)\n![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/burrunan/gradle-cache-action?label=release)\n\nThis is a GitHub Action for caching Gradle caches.\nIn other words, this is [@actions/cache](https://github.com/actions/cache) customized for Gradle.\n\nKey improvements over [@actions/cache](https://github.com/actions/cache) and [gradle-command-action](https://github.com/eskatos/gradle-command-action) are:\n- 🚀 Gradle remote build cache backend (pulls only the needed entries from GitHub cache)\n- 🎉 Support multiple remote caches via [gradle-multi-cache](https://github.com/burrunan/gradle-multi-cache) (e.g. GitHub Actions + S3)\n- 👋 Simplified configuration (action name + gradle command is enough for most case)\n- 👾 Less space usage (GitHub imposes overall 5GiB limit by default, so cache space matters)\n- 🔗 Link to Build Scan in build results\n- 💡 Gradle build failure markers added to the diff view (e.g. `compileJava` or `compileKotlin` markers right in the commit diff)\n\n## Version notes\n\n`v1` uses `node16` which has been deprecated, so consider upgrading to `v2`.\nThe upgrade requires only changing the version, however the newer `node20` might be missing\nif you use an old runner.\n\n## Usage\n\nAdd the following code to your workflow file in the `.github/workflows` directory.\n\nNote: Like with [gradle-command-action](https://github.com/eskatos/gradle-command-action), you can\nspecify `gradle-version: release` to test with the current release version of Gradle, `gradle-version: nightly` for testing Gradle nightly builds,\nan so on (see `gradle-version` below).\n\nNote: For the [security reasons](https://julienrenaux.fr/2019/12/20/github-actions-security-risk/)\nyou might want to use Git SHA rather than branch name or tag name.\nIn other words, to avoid accidental tag update, you might want to use\n`burrunan/gradle-cache-action@03c71a8ba93d670980695505f48f49daf43704a6` rather than `burrunan/gradle-cache-action@v1`.\nPlease see releases page to find out the commit ids: https://github.com/burrunan/gradle-cache-action/releases\n\nYou might use the following references are:\n* `v1`, `v2` -- this is a *moving* qualifier. It points to the latest release among `v1.x`\n* `v1.0`, `v1.1`, ... -- those are fixed versions. They won't change over time\n\nFor the best security you might want to use `burrunan/gradle-cache-action@v3` (see the ids at https://github.com/burrunan/gradle-cache-action/releases)\n\n```yaml\n- uses: burrunan/gradle-cache-action@v3\n  name: Build PROJECT_NAME\n  # Extra environment variables for Gradle execution (regular GitHub Actions feature)\n  # Note: env must be outside of \"with\"\n  env:\n    VARIABLE: VALUE\n  with:\n    # If you have multiple jobs, use distinct job-id in in case you want to split caches\n    # For instance, jobs with different JDK versions can't share caches\n    # RUNNER_OS is added to job-id automatically\n    job-id: jdk8\n    # Specifies arguments for Gradle execution\n    # If arguments is missing or empty, then Gradle is not executed\n    arguments: build\n    # arguments can be multi-line for better readability\n    # arguments: |\n    #  --no-paralell\n    #  build\n    #  -x test\n    # Gradle version to use for execution:\n    #   wrapper (default), current, rc, nightly, release-nightly, or\n    #   versions like 6.6 (see https://services.gradle.org/versions/all)\n    gradle-version: wrapper\n    # Properties are passed as -Pname=value\n    properties: |\n      kotlin.js.compiler=ir\n      kotlin.parallel.tasks.in.project=true\n```\n\nBy default, the action enables the `local` build cache, and it adds a remote build cache\nthat stores the data in GitHub Actions cache.\nHowever, you might want to enable the [Gradle Build Cache](https://docs.gradle.org/current/userguide/build_cache.html)\nfor your local builds to make them faster, or even add a remote cache instance, so your local\nbuilds can reuse artifacts that are build on CI.\n\nThis is how you can enable local build cache (don't forget to add `--build-cache` option or\n`org.gradle.caching=true` property):\n\n```kotlin\n// settings.gradle.kts\nval isCiServer = System.getenv().containsKey(\"CI\")\n// Cache build artifacts, so expensive operations do not need to be re-computed\nbuildCache {\n   local {\n       isEnabled = !isCiServer\n   }\n}\n```\n\n## Sample integrations\n\nHere's how you can integrate build cache to existing projects:\n\n* Apache Calcite: https://github.com/apache/calcite/pull/2114\n* Apache JMeter: https://github.com/apache/jmeter/pull/611\n* pgjdbc: https://github.com/pgjdbc/pgjdbc/pull/1862\n* junit-pioneer: https://github.com/junit-pioneer/junit-pioneer/pull/325\n* opentelemetry-java-instrumentation: https://github.com/open-telemetry/opentelemetry-java-instrumentation/pull/1054\n\n## Configuration\n\nThe default configuration should suit most of the cases, however, there are extra knobs:\n\n```yaml\n- uses: burrunan/gradle-cache-action@v3\n  name: Cache .gradle\n  # Extra environment variables for Gradle execution (regular GitHub Actions feature)\n  env:\n    VARIABLE: VALUE\n  with:\n    # If you have multiple jobs, use distinct job-id in case you want to split caches\n    # For instance, jobs with different JDK versions can't share caches\n    # RUNNER_OS is added to job-id automatically\n    job-id: jdk8\n\n    # Overrides $HOME\n    # home-directory: /home/user\n\n    # Disable caching of $HOME/.gradle/caches/*.*/generated-gradle-jars\n    save-generated-gradle-jars: false\n\n    # Disable remote cache that proxies requests to GitHub Actions cache\n    remote-build-cache-proxy-enabled: false\n\n    # Set the cache key for Gradle version (e.g. in case multiple jobs use different versions)\n    # By default the value is `wrapper`, so the version is determined from the gradle-wrapper.properties   \n    # Note: this argument specifies the version for Gradle execution (if `arguments` is present)\n    # Supported values:\n    #   wrapper (default), current, rc, nightly, release-nightly, or\n    #   versions like 6.6 (see https://services.gradle.org/versions/all)\n    gradle-version: 6.5.1-custom\n\n    # Makes all non-main branch builds to use read-only caching\n    read-only: ${{ github.ref != 'refs/heads/main' }}\n\n    # Uncomment to keep Gradle Daemon after the build\n    # daemon: true\n\n    # Arguments for Gradle execution\n    arguments: build jacocoReport\n\n    # Properties are passed as -Pname=value\n    properties: |\n      kotlin.js.compiler=ir\n      kotlin.parallel.tasks.in.project=true\n\n    # Relative path under $GITHUB_WORKSPACE where Git repository is placed\n    build-root-directory: sub/directory\n\n    # Activates only the caches that are relevant for executing gradle command.\n    # This is helpful when build job executes multiple gradle commands sequentially.\n    # Then the caching is implemented in the very first one, and the subsequent should be marked\n    # with execution-only-caches: true\n    execution-only-caches: true\n\n    # Disable caching of ~/.gradle/caches/build-cache-*\n    save-local-build-cache: false\n\n    # Disable caching of ~/.gradle/caches/modules-*\n    save-gradle-dependencies-cache: false\n\n    # Extra files to take into account for ~/.gradle/caches dependencies\n    gradle-dependencies-cache-key: |\n      gradle/dependencies.kt\n      buildSrc/**/Version.kt\n\n    # Disable caching of ~/.m2/repository/\n    save-maven-dependencies-cache: false\n\n    # Ignore some of the paths when caching Maven Local repository\n    maven-local-ignore-paths: |\n      org/example/\n      com/example/\n\n    # Enable concurrent cache save and restore\n    # Default is concurrent=false for better log readability\n    concurrent: true\n\n    # Disable publishing Gradle Build Scan URL to job report\n    gradle-build-scan-report: false\n\n    # Disable warning about missing distributionSha256Sum property in gradle-wrapper.properties\n    gradle-distribution-sha-256-sum-warning: false\n```\n\n## How does dependency caching work?\n\nThe current GitHub Action's cache (both [actions/cache](https://github.com/actions/cache) action and\n[@actions/cache](https://github.com/actions/toolkit/tree/main/packages/cache) npm package) is immutable.\n\nThe cache can't be updated, so it does not work very good for caches like \"Gradle dependencies\" or \"Maven local repository\".\n\n`gradle-cache-action` creates a layered cache, and it uses a small \"index\" cache to identify the required layers.\nIf only a small fraction of files changes, then the action reuses the existing caches, and it adds a layer on top of it.\nThat enables to save cache space (GitHub has a default limit of 5 GiB), and it reduces upload time as only\nthe cache receives only the updated files.\n\n## How does GitHub Actions-based Gradle remote build cache work?\n\n`gradle-cache-action` launches a small proxy server that listens for Gradle requests and\nthen it redirects the requests to the `@actions/cache` API.\n\nThat makes Gradle believe it is talking to a regular remote cache, and the cache receives\nonly the relevant updates.\nThe increased granularity enables GitHub to evict entries better (it removes unused entries\nautomatically).\n\nThe action configures the URL to the cache proxy via the `~/.gradle/init.gradle` script, and\n[Gradle picks it up automatically](https://docs.gradle.org/current/userguide/init_scripts.html)\n\nNote: Saving GitHub Actions caches might take noticeable time (e.g. 100 ms), so the cache uploads\nin the background. In other words, build scan would show virtually zero response times for\ncache save operations.\n\nIf your build already has a remote cache declared (e.g. you are using your own cache),\nthen `gradle-cache-action` would configure **both** remote caches.\nIt would read from the GitHub cache first, and it would save data to both caches.\n\nThe multi-cache feature can be disabled via `multi-cache-enabled: false`.\n\n## How to enable build scans?\n\n1. Read and agree to the terms of service: https://gradle.com/terms-of-service\n1. Add `--scan` to `arguments:`, and add the following to `settings.gradle.kts`\n\n```kotlin\nplugins {\n    `gradle-enterprise`\n}\n\nval isCiServer = System.getenv().containsKey(\"CI\")\n\nif (isCiServer) {\n    gradleEnterprise {\n        buildScan {\n            termsOfServiceUrl = \"https://gradle.com/terms-of-service\"\n            termsOfServiceAgree = \"yes\"\n            tag(\"CI\")\n        }\n    }\n}\n```\n\n## Why another action instead of gradle-command-action?\n\n`gradle-command-action` was started as a Kotlin/JS experiment for making a customized\n[@actions/cache](https://github.com/actions/cache) that would make Gradle builds faster.\n\nThen it turned out there's a proxy remote cache requests to the `@actions/cache` API can be used when the caching\naction executes Gradle, so the `gradle-cache-action` got a Gradle execution feature.\n\nOf course, the same could have been made in [gradle-command-action](https://github.com/eskatos/gradle-command-action),\nhowever:\n- The author was not familiar with TypeScript ecosystem (stdlib, typical libraries, testing libraries, etc.)\n- Caching logic is collections-heavy, and Kotlin stdlib shines here.\n\n  For instance, in Kotlin `list + list` adds lists, and `array.associateWith { valueFor(it) }` converts arrays to maps.\n  This is easy to write without consulting StackOverflow, the code is readable, and it does not require\n  you [to fight with the compiler](https://blog.johnnyreilly.com/2016/06/create-es2015-map-from-array-in-typescript.html).\n\n- A single language helps when building connected components.\n  `gradle-cache-action` integrates with [gradle-multi-cache](https://github.com/burrunan/gradle-multi-cache) and\n  [gradle-s3-build-cache](https://github.com/burrunan/gradle-s3-build-cache), and they all are Kotlin-based. \n\n## Can I use the caching part of the action only?\n\nYes, you can. If you omit `arguments:`, then the action runs in `cache-only` mode.\nIt won't launch Gradle.\n\n## Can I call multiple different Gradle builds in the same job?\n\nThis might be complicated, see https://github.com/burrunan/gradle-cache-action/issues/15.\n\nCurrently, the workaround is to configure `execution-only-caches: true` for all but one\n`gradle-cache-action` executions.\nThen one of the actions would do the cache save and restore, and the rest would use their own\ncaches only.\n\n## Contributing\n\nContributions are always welcome! If you'd like to contribute (and we hope you do) please open a pull request.\n\n## License\n\nApache 2.0\n\n## Author\n\nVladimir Sitnikov <sitnikov.vladimir@gmail.com>\n"
  },
  {
    "path": "action-types.yml",
    "content": "# See https://github.com/krzema12/github-actions-typing\noutputs:\n  build-scan-url:\n    type: string\ninputs:\n  job-id:\n    type: string\n  build-root-directory:\n    type: string\n  home-directory:\n    type: string\n  gradle-version:\n    type: string\n  read-only:\n    type: boolean\n  save-generated-gradle-jars:\n    type: boolean\n  save-local-build-cache:\n    type: boolean\n  multi-cache-enabled:\n    type: boolean\n  multi-cache-version:\n    type: string\n  multi-cache-repository:\n    type: string\n  multi-cache-group-id-filter:\n    type: string\n  save-gradle-dependencies-cache:\n    type: boolean\n  execution-only-caches:\n    type: boolean\n  remote-build-cache-proxy-enabled:\n    type: boolean\n  gradle-dependencies-cache-key:\n    type: list\n    separator: \"\\n\"\n    list-item:\n      type: string\n  save-maven-dependencies-cache:\n    type: boolean\n  maven-local-ignore-paths:\n    type: list\n    separator: \"\\n\"\n    list-item:\n      type: string\n  debug:\n    type: boolean\n  concurrent:\n    type: boolean\n  arguments:\n    type: list\n    separator: \"\\n\"\n    list-item:\n      type: string\n  properties:\n    type: list\n    separator: \"\\n\"\n    list-item:\n      type: string\n  gradle-build-scan-report:\n    type: boolean\n  gradle-distribution-sha-256-sum-warning:\n    type: boolean\n"
  },
  {
    "path": "action.yml",
    "content": "name: 'Gradle Cache'\ndescription: 'Caches .gradle folder (dependencies, local build cache, ...)'\nauthor: 'Vladimir Sitnikov'\noutputs:\n  build-scan-url:\n    description: Link to the build scan if any\ninputs:\n  job-id:\n    description: A job identifier to avoid cache pollution from different jobs\n    required: false\n  build-root-directory:\n    description: Relative path under $GITHUB_WORKSPACE where Git repository is placed\n    required: false\n  home-directory:\n    description: Overrides the location of $HOME (e.g. to avoid use of /root when running in Docker)\n    required: false\n  gradle-version:\n    description: (wrapper | or explicit version) Caches often depend on the Gradle version, so this parameter sets the ID to use for cache keys. It does not affect the Gradle version used for build\n    required: false\n    default: wrapper\n  read-only:\n    description: Configures caches for read-only opreration (e.g. to save GitHub Actions storage limit)\n    required: false\n    default: false\n  save-generated-gradle-jars:\n    description: Enables caching of $HOME/.gradle/caches/*.*/generated-gradle-jars\n    required: false\n    default: 'true'\n  save-local-build-cache:\n    description: Enables caching of $HOME/.gradle/caches/build-cache-1\n    required: false\n    default: 'true'\n  multi-cache-enabled:\n    description: Adds com.github.burrunan.multi-cache plugin to settings.gradle so GitHub Actions cache can be used in parallel with Gradle remote build cache\n    required: false\n    default: 'true'\n  multi-cache-version:\n    description: Configures com.github.burrunan.multi-cache version to use\n    required: false\n    default: '1.0'\n  multi-cache-repository:\n    description: Configures repository where com.github.burrunan.multi-cache can be located\n    required: false\n    default: ''\n  multi-cache-group-id-filter:\n    description: Configures group id for selecting only com.github.burrunan.multi-cache artifacts (it enables Gradle to use custom repository for multi-cache only)\n    required: false\n    default: 'com[.]github[.]burrunan[.]multi-?cache'\n  save-gradle-dependencies-cache:\n    description: Enables caching of ~/.gradle/caches/modules-*\n    required: false\n    default: 'true'\n  execution-only-caches:\n    description: |\n      Activates only the caches that are relevant for executing gradle command.\n      This is helpful when build job executes multiple gradle commands sequentially.\n      Then the caching is implemented in the very first one, and the subsequent should be marked\n      with execution-only-caches: true\n    required: false\n    default: 'false'\n  remote-build-cache-proxy-enabled:\n    description: Activates a remote cache that proxies requests to GitHub Actions cache\n    required: false\n    default: 'true'\n  gradle-dependencies-cache-key:\n    description: Extra files to take into account for ~/.gradle/caches dependencies\n    required: false\n  save-maven-dependencies-cache:\n    description: Enables caching of ~/.m2/repository/\n    required: false\n    default: 'true'\n  maven-local-ignore-paths:\n    description: Specifies ignored paths in the Maven Local repository (e.g. the artifacts of the current project)\n    required: false\n    default: ''\n  debug:\n    description: Shows extra logging to debug the action\n    required: false\n    default: 'true'\n  daemon:\n    description: Enables or disables Gradle Daemon (--no-daemon). Defaults to false as typically the build executes only once in CI, so there's no much value in keeping the daemon\n    required: false\n    default: 'false'\n  concurrent:\n    description: Enables concurent cache download and upload (disabled by default for better log output)\n    required: false\n    default: 'false'\n  arguments:\n    description: Gradle arguments to pass (optionally multiline)\n    required: false\n  properties:\n    description: Extra Gradle properties (multiline) which would be passed as -Pname=value arguments\n    required: false\n  gradle-build-scan-report:\n    description: Publishes Gradle Build Scan URL to job report.\n    required: false\n    default: 'true'\n  gradle-distribution-sha-256-sum-warning:\n    description: Enables warning when distributionSha256Sum property is missing in gradle-wrapper.properties\n    required: false\n    default: 'true'\nruns:\n  using: node20\n  main: dist/cache-action-entrypoint.js\n  post: dist/cache-action-entrypoint.js\nbranding:\n  icon: archive\n  color: gray-dark\n"
  },
  {
    "path": "build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension\n\nplugins {\n    kotlin(\"multiplatform\") apply false\n}\n\nplugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {\n    configure<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnvSpec> {\n        version = \"22.0.0\"\n    }\n}\n\nsubprojects {\n    if (path != \":wrappers\") {\n        apply(plugin = \"org.jetbrains.kotlin.multiplatform\")\n    }\n}\n\nallprojects {\n    plugins.withId(\"org.jetbrains.kotlin.multiplatform\") {\n        configure<KotlinMultiplatformExtension> {\n            js {\n                compilerOptions {\n                    target = \"es2015\"\n                }\n            }\n        }\n        tasks {\n            withType<AbstractTestTask>().configureEach {\n                testLogging {\n                    showStandardStreams = true\n                }\n            }\n        }\n        configure<KotlinMultiplatformExtension> {\n            js {\n                if (project.name.endsWith(\"-entrypoint\")) {\n                    browser {\n                        testTask {\n                            useMocha {\n                                timeout = \"10000\"\n                            }\n                        }\n                    }\n                    binaries.executable()\n                } else {\n                    nodejs {\n                        testTask {\n                            useMocha {\n                                timeout = \"10000\"\n                                environment(\"RUNNER_TOOL_CACHE\", layout.buildDirectory.dir(\"tool-cache\").get().asFile.toString())\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        dependencies {\n            \"commonMainApi\"(platform(\"org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2\"))\n            \"commonMainApi\"(platform(\"org.jetbrains.kotlinx:kotlinx-serialization-bom:1.9.0\"))\n            \"jsMainImplementation\"(enforcedPlatform(\"org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom:2025.12.7\"))\n            if (project.path != \":test-library\") {\n                \"jsTestImplementation\"(rootProject.projects.testLibrary)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "cache-action-entrypoint/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                implementation(projects.cacheProxy)\n                implementation(projects.gradleLauncher)\n                implementation(projects.layeredCache)\n                implementation(projects.wrappers.actionsToolkit)\n                implementation(projects.wrappers.nodejs)\n                implementation(projects.wrappers.octokitWebhooks)\n                implementation(\"org.jetbrains.kotlin-wrappers:kotlin-actions-io\")\n                implementation(npm(\"string-argv\", \"0.3.1\"))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "cache-action-entrypoint/src/jsMain/kotlin/main.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport actions.core.*\nimport actions.core.ext.getInput\nimport actions.core.ext.getListInput\nimport actions.io.mkdirP\nimport com.github.burrunan.gradle.GradleCacheAction\nimport com.github.burrunan.gradle.Parameters\nimport com.github.burrunan.gradle.github.stateVariable\nimport com.github.burrunan.gradle.proxy.CacheProxy\nimport com.github.burrunan.launcher.LaunchParams\nimport com.github.burrunan.launcher.install\nimport com.github.burrunan.launcher.launchGradle\nimport com.github.burrunan.launcher.resolveDistribution\nimport com.github.burrunan.wrappers.nodejs.normalizedPath\nimport js.globals.globalThis\nimport node.buffer.BufferEncoding\nimport node.fs.writeFile\nimport node.path.path\nimport node.process.process\nimport octokit.currentTrigger\n\nfun String.splitLines() =\n    split(Regex(\"\\\\s*[\\r\\n]+\\\\s*\"))\n        .filter { !it.startsWith(\"#\") && it.contains(\"=\") }\n        .associate {\n            val values = it.split(Regex(\"\\\\s*=\\\\s*\"), limit = 2)\n            values[0] to (values.getOrNull(1) ?: \"\")\n        }\n\nfun isMochaRunning() =\n    arrayOf(\"afterEach\", \"after\", \"beforeEach\", \"before\", \"describe\", \"it\").all {\n        globalThis[it] is Function<*>\n    }\n\nsuspend fun main() {\n    if (isMochaRunning()) {\n        // Ignore if called from tests\n        return\n    }\n    val stageVar = stateVariable(\"stage\") { \"MAIN\" }\n    val stage = ActionStage.values().firstOrNull { it.name == stageVar.get() }\n    // Set next stage\n    stageVar.set(\n        when (stage) {\n            ActionStage.MAIN -> ActionStage.POST\n            null -> {\n                setFailed(\"Unable to find action stage: ${stageVar.get()}\")\n                return\n            }\n            else -> null\n        }?.name ?: \"FINAL\",\n    )\n    try {\n        mainInternal(stage)\n    } catch (e: ActionFailedException) {\n        setFailed(e.message)\n    }\n}\n\nsuspend fun mainInternal(stage: ActionStage) {\n    val homeDirectory = getInput(\"home-directory\").trimEnd('/', '\\\\')\n    if (homeDirectory != \"\") {\n        info(\"Overriding home directory to $homeDirectory\")\n        process.env[\"HOME\"] = homeDirectory\n    }\n\n    val gradleStartArguments = parseArgsStringToArgv(getInput(\"arguments\")).toList()\n    val cacheProxyEnabled = getInput(\"remote-build-cache-proxy-enabled\").ifBlank { \"true\" }.toBoolean()\n\n    val executionOnlyCaches = getInput(\"execution-only-caches\").ifBlank { \"false\" }.toBoolean()\n    val enableBuildScanReport = getInput(\"gradle-build-scan-report\").ifBlank { \"true\" }.toBoolean()\n\n    val buildRootDirectory = getInput(\"build-root-directory\").trimEnd('/', '\\\\')\n    if (buildRootDirectory != \"\") {\n        info(\"changing working directory to $buildRootDirectory\")\n        process.chdir(buildRootDirectory)\n    }\n\n    val params = Parameters(\n        jobId = ActionsEnvironment.RUNNER_OS + \"-\" + getInput(\"job-id\"),\n        path = \".\",\n        debug = getInput(\"debug\").toBoolean(),\n        generatedGradleJars = getInput(\"save-generated-gradle-jars\").ifBlank { \"true\" }.toBoolean(),\n        localBuildCache = (!cacheProxyEnabled || gradleStartArguments.isEmpty()) && getInput(\"save-local-build-cache\").ifBlank { \"true\" }\n            .toBoolean(),\n        gradleDependenciesCache = !executionOnlyCaches && getInput(\"save-gradle-dependencies-cache\").ifBlank { \"true\" }.toBoolean(),\n        gradleDependenciesCacheKey = getListInput(\"gradle-dependencies-cache-key\"),\n        mavenDependenciesCache = !executionOnlyCaches && getInput(\"save-maven-dependencies-cache\").ifBlank { \"true\" }.toBoolean(),\n        mavenLocalIgnorePaths = getListInput(\"maven-local-ignore-paths\"),\n        concurrent = getInput(\"concurrent\").ifBlank { \"false\" }.toBoolean(),\n        readOnly = getInput(\"read-only\").ifBlank { \"false\" }.toBoolean(),\n    )\n\n    val gradleDistribution = resolveDistribution(\n        versionSpec = getInput(\"gradle-version\").ifBlank { \"wrapper\" },\n        projectPath = params.path,\n        distributionUrl = getInput(\"gradle-distribution-url\").ifBlank { null },\n        distributionSha256Sum = getInput(\"gradle-distribution-sha-256-sum\").ifBlank { null },\n        enableDistributionSha256SumWarning = getInput(\"gradle-distribution-sha-256-sum-warning\").ifBlank { \"true\" }.toBoolean(),\n    )\n\n    if (stage == ActionStage.MAIN || stage == ActionStage.POST) {\n        val cacheAction = GradleCacheAction(currentTrigger(), params, gradleDistribution)\n\n        if (params.generatedGradleJars || params.localBuildCache ||\n            params.gradleDependenciesCache || params.mavenDependenciesCache\n        ) {\n            cacheAction.execute(stage)\n        }\n    }\n\n    if (stage == ActionStage.MAIN && gradleStartArguments.isNotEmpty()) {\n        val args = when (params.localBuildCache || cacheProxyEnabled) {\n            true -> listOf(\"--build-cache\") + gradleStartArguments\n            else -> gradleStartArguments\n        }\n        val launchParams = LaunchParams(\n            gradle = install(gradleDistribution),\n            daemon = getInput(\"daemon\").ifBlank { \"false\" }.toBoolean(),\n            projectPath = params.path,\n            arguments = args,\n            properties = getInput(\"properties\").splitLines(),\n        )\n\n        val cacheProxy = CacheProxy()\n\n        if (cacheProxyEnabled) {\n            info(\"Starting remote cache proxy, adding it via ~/.gradle/init.gradle\")\n            cacheProxy.start()\n            val gradleHome = path.join(\"~\".normalizedPath, \".gradle\")\n            mkdirP(gradleHome)\n            writeFile(\n                path.join(gradleHome, \"init.gradle\"),\n                cacheProxy.getMultiCacheConfiguration(\n                    multiCacheEnabled = getInput(\"multi-cache-enabled\").ifBlank { \"true\" }.toBoolean(),\n                    multiCacheVersion = getInput(\"multi-cache-version\").ifBlank { \"1.0\" },\n                    multiCacheRepository = getInput(\"multi-cache-repository\"),\n                    multiCacheGroupIdFilter = getInput(\"multi-cache-group-id-filter\").ifBlank { \"com[.]github[.]burrunan[.]multi-?cache\" },\n                    push = !params.readOnly,\n                ),\n                BufferEncoding.utf8,\n            )\n        }\n\n        try {\n            val result = launchGradle(launchParams)\n            if (enableBuildScanReport) {\n                result.buildScanUrl?.let {\n                    warning(\"Gradle Build Scan: $it\")\n                    setOutput(\"build-scan-url\", it)\n                }\n            }\n        } finally {\n            if (cacheProxyEnabled) {\n                cacheProxy.stop()\n            }\n        }\n    }\n    return\n}\n"
  },
  {
    "path": "cache-action-entrypoint/src/jsMain/kotlin/stringArgv.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n@file:JsModule(\"string-argv\")\n\nexternal fun parseArgsStringToArgv(value: String, env: String = definedExternally, file: String = definedExternally): Array<String>\n"
  },
  {
    "path": "cache-action-entrypoint/src/jsTest/kotlin/com/github/burrunan/ArgumentsTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan\n\nimport parseArgsStringToArgv\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass ArgumentsTest {\n    private fun parse(input: String, vararg output: String) {\n        assertEquals(listOf(*output), parseArgsStringToArgv(input).toList(), input)\n    }\n\n    @Test\n    fun simple() {\n        parse(\"\")\n        parse(\"a b\", \"a\", \"b\")\n        parse(\"a 'b'\", \"a\", \"b\")\n        parse(\"a \\\"b\\\"\", \"a\", \"b\")\n    }\n\n    @Test\n    fun multiline() {\n        parse(\"a\\nb\", \"a\", \"b\")\n        parse(\"a\\n  b\", \"a\", \"b\")\n        parse(\"a\\n  b  \", \"a\", \"b\")\n        parse(\"a\\n  b  \\nc\", \"a\", \"b\", \"c\")\n    }\n\n    @Test\n    fun multilineWithQuotes() {\n        parse(\"'a\\nb'\", \"a\\nb\")\n        parse(\"hello 'a\\n  b' world\", \"hello\", \"a\\n  b\", \"world\")\n        parse(\"hello \\\"a\\n  b\\\" world\", \"hello\", \"a\\n  b\", \"world\")\n    }\n\n    @Test\n    fun withDollars() {\n        parse(\"\\$HOME\", \"\\$HOME\")\n    }\n\n    @Test\n    fun multilineWithComments() {\n        // TODO: \"# commented\" should be ignored\n        parse(\"\"\"\n            build\n            # commented\n            test\n        \"\"\".trimIndent(), \"build\", \"#\", \"commented\", \"test\")\n    }\n}\n"
  },
  {
    "path": "cache-action-entrypoint/src/jsTest/kotlin/com/github/burrunan/SplitLinesTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan\n\nimport splitLines\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass SplitLinesTest {\n    @Test\n    fun empty() {\n        assertEquals(mapOf(\"a\" to \"b\", \"c\" to \"\"), \"a=b\\nc=\".splitLines())\n    }\n\n    @Test\n    fun withoutEquals() {\n        assertEquals(mapOf(\"a\" to \"b\"), \"a=b\\nc\".splitLines())\n    }\n}\n"
  },
  {
    "path": "cache-action-entrypoint/webpack.config.d/config.js",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconfig.output = config.output || {}\nconfig.output.globalObject = \"this\"\nconfig.target = \"node\"\n\nconfig.resolve.modules.unshift(\"src/test/resources\")\n\nconst TerserPlugin = require('terser-webpack-plugin');\n\n// keep_classnames is required to workaround node-fetch Expected signal to be an instanceof AbortSignal\nconfig.optimization = {\n  minimizer: [\n    new TerserPlugin({\n                       parallel: true,\n                       terserOptions: {\n                         // https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions\n                         mangle: false,\n                         sourceMap: true,\n                         // compress: false,\n                         keep_classnames: /AbortSignal/,\n                         keep_fnames: /AbortSignal/,\n                         output: {\n                           beautify: true,\n                           indent_level: 1\n                         }\n                       }\n                     }),\n  ],\n};\n"
  },
  {
    "path": "cache-proxy/build.gradle.kts",
    "content": "import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest\nimport org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha\n\n/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                implementation(projects.cacheServiceMock)\n                implementation(projects.wrappers.actionsCache)\n                implementation(projects.wrappers.actionsToolkit)\n                implementation(projects.wrappers.nodejs)\n                implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-core\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-json\")\n            }\n        }\n    }\n}\n\ntasks.withType<KotlinJsTest>().configureEach {\n    (testFramework as KotlinMocha).timeout = \"60000\"\n}\n"
  },
  {
    "path": "cache-proxy/src/jsMain/kotlin/com/github/burrunan/gradle/proxy/CacheProxy.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.gradle.proxy\n\nimport actions.cache.RestoreType\nimport actions.cache.restoreAndLog\nimport actions.core.LogLevel\nimport actions.glob.removeFiles\nimport com.github.burrunan.gradle.cache.HttpException\nimport com.github.burrunan.gradle.cache.handle\nimport com.github.burrunan.wrappers.nodejs.mkdir\nimport com.github.burrunan.wrappers.nodejs.pipeAndWait\nimport js.objects.unsafeJso\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport node.fs.createReadStream\nimport node.fs.createWriteStream\nimport node.fs.stat\nimport node.http.IncomingMessage\nimport node.http.OutgoingHttpHeaders\nimport node.http.ServerResponse\nimport node.net.AddressInfo\nimport node.path.path\nimport node.process.process\nimport kotlin.coroutines.resume\nimport kotlin.coroutines.suspendCoroutine\n\nclass CacheProxy {\n    companion object {\n        const val GHA_CACHE_URL = \"GHA_CACHE_URL\"\n        private const val TEMP_DIR = \".cache-proxy\"\n        private val cacheVersion = \"1-\"\n    }\n\n    private var _cacheUrl: String? = null\n\n    val cacheUrl: String? get() = _cacheUrl\n\n    private val server = node.http.createServer<IncomingMessage, ServerResponse<*>> { req, res ->\n        val query = node.url.parse(req.url!!, true)\n        val path = query.pathname ?: \"\"\n        res.handle {\n            val id = path.removePrefix(\"/\")\n            when (req.method) {\n                \"GET\" -> getEntry(id, res)\n                \"PUT\" -> putEntry(id, req, res)\n                else -> HttpException.notImplemented(\"Not implemented: ${req.method}\")\n            }\n        }\n    }\n\n//    private val compression = jso<InternalCacheOptions> { compressionMethod = CompressionMethod.Gzip }\n\n    private suspend fun putEntry(id: String, req: IncomingMessage, res: ServerResponse<*>) {\n        val fileName = path.join(TEMP_DIR, \"bc-$id\")\n        try {\n            req.pipeAndWait(createWriteStream(fileName))\n            res.writeHead(200, \"OK\", undefined.unsafeCast<OutgoingHttpHeaders>())\n        } finally {\n            GlobalScope.launch {\n                try {\n                    actions.cache.saveAndLog(listOf(fileName), id, cacheVersion, logLevel = LogLevel.DEBUG)\n                } finally {\n                    removeFiles(listOf(fileName))\n                }\n            }\n        }\n    }\n\n    private suspend fun getEntry(id: String, res: ServerResponse<*>) {\n        val fileName = path.join(TEMP_DIR, \"bc-$id\")\n        val restoreType = restoreAndLog(listOf(fileName), id, restoreKeys = listOf(), version = cacheVersion, logLevel = LogLevel.DEBUG)\n        if (restoreType == RestoreType.None) {\n            throw HttpException.notFound(\"No cache entry found for $id\")\n        }\n        res.writeHead(\n            200, \"Ok\",\n            unsafeJso<OutgoingHttpHeaders> {\n                contentLength = stat(fileName).size\n            },\n        )\n        createReadStream(fileName).pipeAndWait(res)\n    }\n\n    private val pluginId = \"com.github.burrunan.multi-cache\"\n\n    fun getMultiCacheConfiguration(\n        multiCacheEnabled: Boolean = true,\n        multiCacheVersion: String = \"1.0\",\n        multiCacheRepository: String = \"\",\n        multiCacheGroupIdFilter: String = \"com[.]github[.]burrunan[.]multi-?cache\",\n        push: Boolean = true,\n    ): String {\n        val multiCacheGroupIdFilterEscaped = multiCacheGroupIdFilter.replace(\"\\\\\", \"\\\\\\\\\")\n        //language=Groovy\n        return \"\"\"\n            def pluginId = 'com.github.burrunan.multi-cache'\n            def multiCacheVersion = '1.0'\n            def multiCacheGroupIdFilter = 'com[.]github[.]burrunan[.]multi-?cache'\n            boolean multiCacheEnabled = $multiCacheEnabled\n            String multiCacheRepository = '$multiCacheRepository'\n            boolean gradle6Plus = org.gradle.util.GradleVersion.current() >= org.gradle.util.GradleVersion.version('6.0')\n            // beforeSettings is Gradle 6.0+\n            if (multiCacheEnabled && !gradle6Plus) {\n                println(\"Multiple remote build caches ($pluginId) are supported in Gradle 6.0+ only\")\n                multiCacheEnabled = false\n            }\n            if (multiCacheEnabled) {\n                beforeSettings { settings ->\n                    def repos = settings.buildscript.repositories\n                    if (multiCacheRepository != '') {\n                        repos.add(\n                            repos.maven {\n                                url = multiCacheRepository\n                                if ('$multiCacheGroupIdFilterEscaped' != '') {\n                                    content {\n                                        includeGroupByRegex('$multiCacheGroupIdFilterEscaped')\n                                    }\n                                }\n                            }\n                        )\n                    } else if (repos.isEmpty()) {\n                        repos.add(repos.gradlePluginPortal())\n                    }\n                    settings.buildscript.dependencies {\n                        classpath(\"$pluginId:${pluginId}.gradle.plugin:$multiCacheVersion\")\n                    }\n                }\n            }\n\n            settingsEvaluated { settings ->\n                settings.buildCache {\n                    boolean needMulticache = remote != null\n                    if (needMulticache && !multiCacheEnabled) {\n                        println(\"$pluginId is disabled\")\n                        return\n                    }\n\n                    local {\n                        enabled = true\n                        push = $push\n                    }\n                    if (needMulticache) {\n                        settings.pluginManager.apply(\"$pluginId\")\n                        settings.multicache.push('base')\n                    }\n                    remote(HttpBuildCache) {\n                        url = '$cacheUrl'\n                        push = $push\n                        // Build cache is located on localhost, so it is fine to use http protocol\n                        if (gradle6Plus) {\n                            allowInsecureProtocol = true\n                        }\n                    }\n                    if (needMulticache) {\n                        settings.multicache.pushAndConfigure('actions-cache') {\n                            loadSequentiallyWriteConcurrently('actions-cache', 'base')\n                        }\n                    }\n                }\n            }\n        \"\"\".trimIndent()\n    }\n\n    suspend fun start() {\n        suspendCoroutine<Nothing?> { cont ->\n            server.listen(0) {\n                cont.resume(null)\n            }\n        }\n\n        mkdir(TEMP_DIR)\n        val url = \"http://localhost:${(server.address().unsafeCast<AddressInfo>()).port}/\"\n        _cacheUrl = url\n        process.env[GHA_CACHE_URL] = url\n    }\n\n    fun stop() {\n        server.close()\n    }\n\n    suspend inline operator fun <T> invoke(block: () -> T): T {\n        start()\n        try {\n            return block()\n        } finally {\n            stop()\n        }\n    }\n}\n"
  },
  {
    "path": "cache-proxy/src/jsTest/kotlin/com/github/burrunan/gradle/proxy/CacheProxyTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.gradle.proxy\n\nimport actions.exec.ExecOptions\nimport actions.exec.exec\nimport actions.glob.removeFiles\nimport com.github.burrunan.gradle.cache.CacheService\nimport com.github.burrunan.test.runTest\nimport com.github.burrunan.wrappers.nodejs.mkdir\nimport kotlinx.serialization.json.Json\nimport kotlinx.serialization.json.encodeToDynamic\nimport node.buffer.BufferEncoding\nimport node.fs.copyFile\nimport node.fs.writeFile\nimport node.process.process\nimport kotlin.test.Test\nimport kotlin.test.assertContains\nimport kotlin.test.fail\n\nclass CacheProxyTest {\n    // Emulates Azure Cache Backend for @actions/cache\n    val cacheService = CacheService()\n\n    // Implements Gradle HTTP Build Cache via @actions/cache\n    val cacheProxy = CacheProxy()\n\n    @Test\n    fun abc() = runTest {\n        val z = mapOf(\"a\" to 4, \"b\" to 6)\n        println(\"json: \" + JSON.stringify(Json.encodeToDynamic(z)))\n    }\n\n    @Test\n    fun cacheProxyWorks() = runTest {\n        val dir = \"remote_cache_test\"\n        mkdir(dir)\n        val root = process.cwd() + \"/../../../..\"\n        console.log(root)\n        cacheService {\n            cacheProxy {\n                val outputFile = \"build/out.txt\"\n                removeFiles(listOf(\"$dir/$outputFile\"))\n                copyFile(\"$root/gradlew\", dir + \"/gradlew\")\n                mkdir(\"$dir/gradle\")\n                mkdir(\"$dir/gradle/wrapper\")\n                copyFile(\"$root/gradle/wrapper/gradle-wrapper.jar\", \"$dir/gradle/wrapper/gradle-wrapper.jar\")\n                copyFile(\"$root/gradle/wrapper/gradle-wrapper.properties\", \"$dir/gradle/wrapper/gradle-wrapper.properties\")\n                writeFile(\n                    \"$dir/settings.gradle\",\n                    \"\"\"\n                        rootProject.name = 'sample'\n                        boolean gradle6Plus = org.gradle.util.GradleVersion.current() >= org.gradle.util.GradleVersion.version('6.0')\n                        buildCache {\n                            local {\n                                // Only remote cache should be used\n                                enabled = false\n                            }\n                            remote(HttpBuildCache) {\n                                url = '${process.env[\"GHA_CACHE_URL\"]}'\n                                push = true\n                                if (gradle6Plus) {\n                                    allowInsecureProtocol = true\n                                }\n                            }\n                        }\n                    \"\"\".trimIndent(),\n                    BufferEncoding.utf8,\n                )\n                writeFile(\n                    \"$dir/build.gradle\",\n                    \"\"\"\n                        tasks.create('props', WriteProperties) {\n                          outputFile = file(\"$outputFile\")\n                          property(\"hello\", \"world\")\n                        }\n                        tasks.create('props2', WriteProperties) {\n                          outputFile = file(\"${outputFile}2\")\n                          property(\"hello\", \"world2\")\n                        }\n                    \"\"\".trimIndent(),\n                    BufferEncoding.utf8,\n                )\n                writeFile(\n                    \"$dir/gradle.properties\",\n                    \"\"\"\n                    org.gradle.caching=true\n                    #org.gradle.caching.debug=true\n                    org.gradle.configuration-cache=true\n                    \"\"\".trimIndent(),\n                    BufferEncoding.utf8,\n                )\n                val out = exec(\"./gradlew\", \"props\", \"-i\", \"--build-cache\", captureOutput = true) {\n                    ExecOptions.copy(it,\n                        cwd = dir,\n                        silent = true,\n                        ignoreReturnCode = true,\n                    )\n                }\n                if (out.exitCode != 0) {\n                    fail(\"Unable to execute :props task: STDOUT: ${out.stdout}, STDERR: ${out.stderr}\")\n                }\n                assertContains(\n                    out.stdout,\n                    \"1 actionable task: 1 executed\",\n                )\n\n                removeFiles(listOf(\"$dir/$outputFile\"))\n                val out2 = exec(\"./gradlew\", \"props\", \"-i\", \"--build-cache\", captureOutput = true) {\n                    ExecOptions.copy(it,\n                        cwd = dir,\n                        silent = true,\n                        ignoreReturnCode = true,\n                    )\n                }\n                if (out.exitCode != 0) {\n                    fail(\"Unable to execute :props task: STDOUT: ${out.stdout}, STDERR: ${out.stderr}\")\n                }\n                assertContains(out2.stdout, \"1 actionable task: 1 from cache\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "cache-service-mock/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                implementation(projects.wrappers.actionsCache)\n                implementation(projects.wrappers.actionsToolkit)\n                implementation(projects.wrappers.nodejs)\n                implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-core\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "cache-service-mock/src/jsMain/kotlin/com/github/burrunan/gradle/cache/CacheService.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport actions.cache.internal.*\nimport actions.core.debug\nimport com.github.burrunan.wrappers.js.suspendWithCallback\nimport com.github.burrunan.wrappers.nodejs.exists\nimport com.github.burrunan.wrappers.nodejs.readJson\nimport com.github.burrunan.wrappers.nodejs.readToBuffer\nimport js.objects.unsafeJso\nimport node.http.IncomingMessage\nimport node.http.OutgoingHttpHeaders\nimport node.http.ServerResponse\nimport node.net.AddressInfo\nimport node.process.process\nimport node.querystring.ParsedUrlQuery\nimport node.url.Url\nimport kotlin.coroutines.resume\nimport kotlin.coroutines.suspendCoroutine\n\nclass CacheService {\n    companion object {\n        const val ARCHIVE_DOWNLOAD_URL = \"_apis/artifactcache/get\"\n    }\n\n    private val storage = CacheStorage()\n\n    private val server = node.http.createServer<IncomingMessage, ServerResponse<*>> { req, res ->\n        val query = node.url.parse(req.url!!, true)\n        val path = query.pathname ?: \"\"\n        res.handle {\n            when {\n                path == \"/_apis/artifactcache/caches\" && req.method == \"POST\" ->\n                    reserveCache(req, res)\n                path == \"/_apis/artifactcache/cache\" && req.method == \"GET\" ->\n                    getCache(query, res)\n                path.endsWith(ARCHIVE_DOWNLOAD_URL) && req.method == \"GET\" ->\n                    getContents(query, res)\n                path.startsWith(\"/_apis/artifactcache/caches/\") ->\n                    cacheOp(path.substringAfter(\"/_apis/artifactcache/caches/\").toInt(), req, res)\n                else -> HttpException.notImplemented(\"Path: $path\")\n            }\n        }\n    }\n\n    private fun getContents(query: Url, res: ServerResponse<*>) {\n        val key = query.query.unsafeCast<ParsedUrlQuery>()[\"key\"] as String\n        val entry = storage.getValue(key)\n        res.writeHead(\n            200, \"Ok\",\n            unsafeJso<OutgoingHttpHeaders> {\n                contentLength = entry.value.length\n            },\n        )\n        res.write(entry.value)\n    }\n\n    private suspend fun cacheOp(cacheId: Number, req: IncomingMessage, res: ServerResponse<*>) = when (req.method) {\n        \"PATCH\" -> uploadCache(cacheId, req, res)\n        \"POST\" -> commitCache(cacheId, req, res)\n        else -> throw HttpException.notImplemented(\"Unknown method: ${req.method}\")\n    }\n\n    private fun getCache(query: Url, res: ServerResponse<*>) {\n        val request = query.query.unsafeCast<GetCacheParams>()\n        var resultKey: String? = null\n        var resultEntry: CacheEntry? = null\n        for ((index, key) in request.keys.split(',').withIndex()) {\n            if (index == 0) {\n                val entry = storage[key] ?: continue\n                if (entry.version != request.version) {\n                    debug(\"Entry version differs for key $key. Requested: ${request.version}, actual: ${entry.version}\")\n                }\n                resultKey = key\n                resultEntry = entry\n                break\n            }\n            val entry = storage.find(key, request.version) ?: continue\n            resultKey = entry.key\n            resultEntry = entry.value\n        }\n        if (resultKey == null) {\n            throw HttpException.noContent(\"No entries found\")\n        }\n\n        res.writeHead(200, \"Ok\", undefined.unsafeCast<OutgoingHttpHeaders>())\n\n        res.write(\n            JSON.stringify(\n                unsafeJso<ArtifactCacheEntry> {\n                    cacheKey = resultKey\n                    scope = \"refs/origin/main\"\n                    creationTime = resultEntry?.creationTime?.toString()\n                    archiveLocation =\n                        \"${process.env[\"ACTIONS_CACHE_URL\"]}$ARCHIVE_DOWNLOAD_URL?key=$resultKey\".takeIf { resultEntry != null }\n                },\n            ),\n        )\n    }\n\n    private suspend fun uploadCache(cacheId: Number, req: IncomingMessage, res: ServerResponse<*>) {\n        val contentRange = req.headers.asDynamic()[\"content-range\"] as String\n        val (_, start, end) = contentRange.match(\"bytes (\\\\d+)-(\\\\d+)\") ?: arrayOf(\"\", \"\", \"\")\n        if (start.isEmpty()) {\n            throw HttpException.notImplemented(\"Unknown content-range: $contentRange\")\n        }\n        storage.update(cacheId, start.toInt(), end.toInt(), req.readToBuffer())\n        res.writeHead(200, \"OK\", undefined.unsafeCast<OutgoingHttpHeaders>())\n    }\n\n    private suspend fun commitCache(cacheId: Number, req: IncomingMessage, res: ServerResponse<*>) {\n        storage.commitCache(cacheId, req.readJson<CommitCacheRequest>().size)\n        res.writeHead(200, \"OK\", undefined.unsafeCast<OutgoingHttpHeaders>())\n    }\n\n    private suspend fun reserveCache(req: IncomingMessage, res: ServerResponse<*>) {\n        if (req.method != \"POST\") {\n            throw HttpException.badRequest(\"Expecting POST method, got ${req.method}\")\n        }\n        val request = req.readJson<ReserveCacheRequest>()\n\n        val cacheId = storage.reserveCache(request.key, request.version!!)\n            ?: throw HttpException.badRequest(\"Cache entry already exists\")\n        res.writeHead(200, \"Reserve Cache OK\", undefined.unsafeCast<OutgoingHttpHeaders>())\n        res.write(\n            JSON.stringify(\n                unsafeJso<ReserveCacheResponse> {\n                    this.cacheId = cacheId\n                },\n            ),\n        )\n    }\n\n    suspend inline operator fun <T> invoke(block: () -> T): T {\n        start()\n        try {\n            return block()\n        } finally {\n            stop()\n        }\n    }\n\n    suspend fun start() {\n        suspendCoroutine<Nothing?> { cont ->\n            server.listen(0) {\n                cont.resume(null)\n            }\n        }\n\n        val runnerTemp = \"runner_temp\"\n        if (!exists(runnerTemp)) {\n            com.github.burrunan.wrappers.nodejs.mkdir(runnerTemp)\n        }\n\n        process.env[\"ACTIONS_RUNTIME_TOKEN\"] = \"42\"\n        process.env[\"RUNNER_TEMP\"] = process.cwd() + \"/\" + runnerTemp\n        process.env[\"ACTIONS_CACHE_URL\"] = \"http://localhost:${(server.address().unsafeCast<AddressInfo>()).port}/\"\n    }\n\n    suspend fun stop() {\n        suspendWithCallback { server.close(it) }\n    }\n}\n"
  },
  {
    "path": "cache-service-mock/src/jsMain/kotlin/com/github/burrunan/gradle/cache/CacheStorage.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport node.buffer.Buffer\n\nclass CacheStorage {\n    private val storage = mutableMapOf<String, CacheEntry>()\n    private val reservations = mutableMapOf<String, CacheReservation>()\n    private val caches = mutableMapOf<Number, TemporaryCache>()\n    private var nextId = 0\n\n    fun reserveCache(key: String, version: String): Number? {\n        if (key in storage || key in reservations) {\n            return null\n        }\n        if (reservations[key]?.version?.equals(version) == false) {\n            return null\n        }\n        nextId += 1\n        reservations[key] = CacheReservation(nextId, version)\n        caches[nextId] = TemporaryCache(key)\n        return nextId\n    }\n\n    operator fun set(key: String, value: CacheEntry) {\n        storage[key] = value\n    }\n\n    operator fun get(key: String) = storage[key]\n\n    fun getValue(key: String) = storage.getValue(key)\n\n    fun find(prefix: String, version: String) =\n        storage.filterKeys { it.startsWith(prefix) }\n            .filterValues { it.version == version }\n            .maxByOrNull { it.value.creationTime.toDouble() }\n\n    fun update(cacheId: Number, start: Int, end: Int, buffer: Buffer<*>) {\n        caches.getValue(cacheId).parts.add(UploadPart(start, end, buffer))\n    }\n\n    fun commitCache(cacheId: Number, size: Number) {\n        val cache = caches.remove(cacheId)\n            ?: throw HttpException.noContent(\"Cache $cacheId is not found\")\n        val reservation = reservations.remove(cache.key)\n            ?: throw HttpException.noContent(\"Reservation ${cache.key} is not found for cache $cacheId\")\n\n        val parts = cache.parts\n        val result = if (parts.size == 1 && parts[0].contents.length == size) {\n            parts[0].contents\n        } else {\n            Buffer.alloc(size).also {\n                for (part in parts) {\n                    part.contents.copy(it, part.start, 0, part.end)\n                }\n            }\n        }\n        set(cache.key, CacheEntry(reservation.version, result, cacheId))\n    }\n}\n\nclass CacheEntry(val version: String, val value: Buffer<*>, val creationTime: Number)\n\nclass CacheReservation(val number: Number, val version: String)\n\nclass TemporaryCache(val key: String) {\n    val parts = mutableListOf<UploadPart>()\n}\n\nclass UploadPart(val start: Int, val end: Int, val contents: Buffer<*>)\n"
  },
  {
    "path": "cache-service-mock/src/jsMain/kotlin/com/github/burrunan/gradle/cache/HttpException.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nclass HttpException(val code: Int, message: String) : Throwable(message) {\n    companion object {\n        fun noContent(message: String) = HttpException(204, message)\n        fun notImplemented(message: String) = HttpException(501, message)\n        fun notFound(message: String) = HttpException(404, message)\n        fun badRequest(message: String) = HttpException(400, message)\n    }\n}\n"
  },
  {
    "path": "cache-service-mock/src/jsMain/kotlin/com/github/burrunan/gradle/cache/HttpExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport kotlinx.coroutines.CoroutineScope\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.supervisorScope\nimport node.http.OutgoingHttpHeaders\nimport node.http.ServerResponse\n\nfun ServerResponse<*>.handle(action: suspend CoroutineScope.() -> Unit) =\n    GlobalScope.launch {\n        try {\n            supervisorScope {\n                action()\n            }\n        } catch (e: HttpException) {\n            writeHead(e.code, e.message ?: \"no message\", undefined.unsafeCast<OutgoingHttpHeaders>())\n        } catch (e: Throwable) {\n            e.printStackTrace()\n            writeHead(500, \"Error processing ${e.message}\", undefined.unsafeCast<OutgoingHttpHeaders>())\n        } finally {\n            end()\n        }\n    }\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.14.3-bin.zip\nnetworkTimeout=10000\nvalidateDistributionUrl=true\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle-launcher/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                implementation(projects.hashing)\n                implementation(projects.wrappers.actionsToolkit)\n                implementation(projects.wrappers.javaProperties)\n                implementation(projects.wrappers.nodejs)\n                implementation(\"org.jetbrains.kotlin-wrappers:kotlin-actions-http-client\")\n                implementation(\"org.jetbrains.kotlin-wrappers:kotlin-actions-tool-cache\")\n                implementation(\"org.jetbrains.kotlin-wrappers:kotlin-actions-io\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-core\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/GradleDistribution.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\ndata class GradleDistribution(\n    val version: String,\n    val distributionUrl: String,\n    val distributionSha256Sum: String?,\n)\n\nsuspend fun resolveDistribution(\n    versionSpec: String,\n    projectPath: String,\n    distributionUrl: String? = null,\n    distributionSha256Sum: String? = null,\n    enableDistributionSha256SumWarning: Boolean = true\n): GradleDistribution {\n    return if (distributionUrl == null) {\n        when (val version = GradleVersion(versionSpec)) {\n            is GradleVersion.Official -> version.findUrl()\n            is GradleVersion.Dynamic -> version.findUrl()\n            is GradleVersion.Wrapper -> findVersionFromWrapper(projectPath, enableDistributionSha256SumWarning)\n        }\n    } else {\n        GradleDistribution(\n            version = versionSpec,\n            distributionUrl = distributionUrl,\n            distributionSha256Sum = distributionSha256Sum ?: \"$distributionUrl.sha256\",\n        )\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/GradleInstaller.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\nimport actions.core.ActionFailedException\nimport actions.core.info\nimport actions.core.warning\nimport actions.http.client.HttpClient\nimport actions.http.client.HttpCodes\nimport actions.io.rmRF\nimport actions.tool.cache.cacheDir\nimport actions.tool.cache.downloadTool\nimport actions.tool.cache.extractZip\nimport com.github.burrunan.hashing.hashFiles\nimport com.github.burrunan.wrappers.nodejs.exists\nimport js.objects.unsafeJso\nimport js.promise.await\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.launch\nimport node.buffer.BufferEncoding\nimport node.fs.chmod\nimport node.fs.readFile\nimport node.http.OutgoingHttpHeaders\nimport node.path.path\nimport node.process.Platform\n\nsuspend fun install(distribution: GradleDistribution): String {\n    val cachedTool = actions.tool.cache.find(\"gradle\", distribution.version)\n    val gradleDir = if (cachedTool.isNotEmpty()) {\n        info(\"Detected Gradle ${distribution.version} at $cachedTool\")\n        cachedTool\n    } else {\n        val gradleZip = downloadTool(distribution.distributionUrl)\n        distribution.distributionSha256Sum?.let { expectedSha256 ->\n            val hash = hashFiles(gradleZip, algorithm = \"sha256\", includeFileName = false).hash\n            if (hash != expectedSha256) {\n                throw ActionFailedException(\n                    \"Checksum mismatch for Gradle ${distribution.version} (${distribution.distributionUrl}). \" +\n                        \"Expected: $expectedSha256, actual: $hash\",\n                )\n            }\n        }\n        val extractedGradleDir = extractZip(gradleZip)\n        cacheDir(path.join(extractedGradleDir, \"gradle-${distribution.version}\"), \"gradle\", distribution.version).also {\n            GlobalScope.launch {\n                // Remove temporary files\n                rmRF(gradleZip)\n                rmRF(extractedGradleDir)\n            }\n        }\n    }\n    return path.join(gradleDir, \"bin\", if (node.os.platform() == Platform.win32) \"gradle.bat\" else \"gradle\").also {\n        if (node.os.platform() != Platform.win32) {\n            chmod(it, \"755\".toInt(8))\n        }\n    }\n}\n\nprivate val HTTP_AGENT =\n    unsafeJso<OutgoingHttpHeaders> {\n        set(\"User-Agent\", \"burrunan/gradle-cache-action\")\n    }\n\nsuspend fun GradleVersion.Official.findUrl(): GradleDistribution {\n    val url = \"https://services.gradle.org/versions/all\"\n    val response =\n        HttpClient().getJson<Array<GradleVersionResponse>>(url, HTTP_AGENT).await()\n    if (response.statusCode.unsafeCast<HttpCodes>() != HttpCodes.OK) {\n        throw ActionFailedException(\"Unable to lookup $url Gradle version: ${response.statusCode}, ${JSON.stringify(response.result)}\")\n    }\n    return response.result?.firstOrNull { it.version == name }?.resolveChecksum()\n        ?: throw ActionFailedException(\"Unable to find Gradle version $name\")\n}\n\nsuspend fun GradleVersion.Dynamic.findUrl(): GradleDistribution {\n    val url = \"https://services.gradle.org/versions/$apiPath\"\n    val response = HttpClient().getJson<dynamic>(url, HTTP_AGENT).await()\n    if (response.statusCode.unsafeCast<HttpCodes>() != HttpCodes.OK) {\n        throw ActionFailedException(\"Unable to lookup $url Gradle version: ${response.statusCode}, ${JSON.stringify(response.result)}\")\n    }\n    if (response.result?.version != null) {\n        return response.result.unsafeCast<GradleVersionResponse>().resolveChecksum()\n    }\n    if (this is GradleVersion.ReleaseCandidate) {\n        return GradleVersion.Current.findUrl()\n    }\n    throw ActionFailedException(\"Empty result from $url: ${JSON.stringify(response.result)}\")\n}\n\nsuspend fun GradleVersionResponse.resolveChecksum() =\n    GradleDistribution(\n        version = version,\n        distributionUrl = downloadUrl,\n        distributionSha256Sum = HttpClient().get(checksumUrl, HTTP_AGENT).await().readBody().await().trim(),\n    )\n\nsuspend fun findVersionFromWrapper(projectPath: String, enableDistributionSha256SumWarning: Boolean): GradleDistribution {\n    val gradleWrapperProperties = path.join(projectPath, \"gradle\", \"wrapper\", \"gradle-wrapper.properties\")\n    if (!exists(gradleWrapperProperties)) {\n        warning(\"Gradle wrapper configuration is not found at ${path.resolve(gradleWrapperProperties)}.\\nWill use the current release Gradle version\")\n        return GradleVersion.Current.findUrl()\n    }\n    val propString = readFile(gradleWrapperProperties, BufferEncoding.utf8)\n    val props = javaproperties.parseString(propString).run {\n        getKeys().associateWith { getFirst(it)!! }\n    }\n\n    val distributionUrl = props.getValue(\"distributionUrl\")\n    val distributionSha256Sum = props[\"distributionSha256Sum\"]\n\n    val version = distributionUrl.substringAfterLast(\"/\")\n        .substringAfter(\"gradle-\")\n        .removeSuffix(\"-all.zip\")\n        .removeSuffix(\"-bin.zip\")\n        .removeSuffix(\".zip\")\n\n    if (enableDistributionSha256SumWarning && distributionSha256Sum == null) {\n        warning(\n            \"distributionSha256Sum is not set in $gradleWrapperProperties.\\n\" +\n                \"Please consider adding the checksum, \" +\n                \"see https://docs.gradle.org/current/userguide/gradle_wrapper.html#configuring_checksum_verification\",\n        )\n    }\n\n    return if (distributionUrl.removePrefix(\"https\").removePrefix(\"http\")\n            .startsWith(\"://services.gradle.org/\")\n    ) {\n        // Official release, use shorter version\n        //   https://services.gradle.org/distributions-snapshots/gradle-6.7-20200730220045+0000-all.zip\n        //   https://services.gradle.org/distributions/gradle-6.6-rc-4-all.zip\n        //   https://services.gradle.org/distributions/gradle-6.5.1-all.zip\n        if (distributionUrl.endsWith(\"-bin.zip\") && distributionSha256Sum != null) {\n            GradleDistribution(version, distributionUrl, distributionSha256Sum)\n        } else {\n            // Resolve checksum from the official site\n            // This would switch to -bin distribution which is smaller\n            GradleVersion.Official(version).findUrl()\n        }\n    } else {\n        GradleDistribution(version, distributionUrl, distributionSha256Sum)\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/GradleLauncher.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.launcher\n\nimport actions.core.AnnotationProperties\nimport actions.core.ExitCode\nimport actions.core.setFailed\nimport actions.core.setOutput\nimport actions.exec.ExecListeners\nimport actions.exec.ExecOptions\nimport actions.exec.exec\nimport com.github.burrunan.launcher.internal.GradleErrorCollector\nimport com.github.burrunan.launcher.internal.GradleOutErrorCollector\nimport node.process.process\n\nclass GradleResult(\n    val buildScanUrl: String?,\n)\n\nsuspend fun launchGradle(params: LaunchParams): GradleResult {\n    var buildScanUrl: String? = null\n    // See https://youtrack.jetbrains.com/issue/KT-41107\n    var failureDetected = false\n    val errorCollector = GradleErrorCollector()\n    val outCollector = GradleOutErrorCollector()\n\n    @Suppress(\"REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_FUNCTION\")\n    val result = exec(\n        params.gradle,\n        args = *(if (params.daemon) emptyList() else listOf(\"--no-daemon\") +\n            params.properties.map { \"-P${it.key}=${it.value}\" } +\n            params.arguments).toTypedArray(),\n    ) {\n        ExecOptions.copy(\n            it,\n            cwd = params.projectPath,\n            ignoreReturnCode = true,\n            listeners = ExecListeners(\n                stdline = {\n                    val str = it.trimEnd()\n                    if (str.startsWith(\"https://gradle.com/s/\")) {\n                        setOutput(\"build-scan-url\", str)\n                        buildScanUrl = str\n                    }\n                    outCollector.process(str)\n                },\n                errline = {\n                    errorCollector.process(it)\n                    outCollector.process(it)\n                },\n            )\n        )\n    }\n    errorCollector.done()\n    outCollector.done()\n    for (error in errorCollector.errors + outCollector.errors) {\n        failureDetected = true\n        val shortFile = error.file\n            ?.removePrefix(process.cwd())\n        actions.core.error(\n            error.message,\n            AnnotationProperties(\n                file = shortFile,\n                startLine = error.line,\n                startColumn = error.col,\n            ),\n        )\n    }\n    if (failureDetected) {\n        process.exitCode = ExitCode.Failure.unsafeCast<Double>()\n    }\n    if (!failureDetected && result.exitCode != 0) {\n        setFailed(\"Gradle process finished with a non-zero exit code: ${result.exitCode}\")\n    }\n    return GradleResult(buildScanUrl)\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/GradleVersion.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\nsealed class GradleVersion(val name: String, unused: Int = 0) {\n    companion object {\n        val DYNAMIC_VERSIONS = listOf(\n            Current,\n            ReleaseCandidate,\n            Nightly,\n            ReleaseNightly,\n        )\n        val FIXED_VERSIONS = DYNAMIC_VERSIONS + Wrapper\n    }\n\n    abstract class Dynamic(label: String, val apiPath: String) : GradleVersion(label)\n    class Official(label: String) : GradleVersion(label) {\n        override fun toString() = \"Official($name)\"\n    }\n\n    object Current : Dynamic(\"current\", \"current\") {\n        override fun toString() = \"Current\"\n    }\n\n    object ReleaseCandidate : Dynamic(\"rc\", \"release-candidate\") {\n        override fun toString() = \"ReleaseCandidate\"\n    }\n\n    object Nightly : Dynamic(\"nightly\", \"nightly\") {\n        override fun toString() = \"Nightly\"\n    }\n\n    object ReleaseNightly : Dynamic(\"release-nightly\", \"release-nightly\") {\n        override fun toString() = \"ReleaseNightly\"\n    }\n\n    object Wrapper : GradleVersion(\"wrapper\") {\n        override fun toString() = \"Wrapper\"\n    }\n}\n\nfun GradleVersion(version: String) =\n    GradleVersion.FIXED_VERSIONS.firstOrNull { it.name == version }\n        ?: GradleVersion.Official(version)\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/GradleVersionResponse.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\nexternal interface GradleVersionResponse {\n    val version: String\n    val downloadUrl: String\n    val checksumUrl: String\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/LaunchParams.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\nclass LaunchParams(\n    val gradle: String,\n    val daemon: Boolean,\n    val projectPath: String,\n    val arguments: List<String>,\n    val properties: Map<String, String>,\n)\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/internal/GradleError.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher.internal\n\nclass GradleError(\n    val message: String,\n    val file: String? = null,\n    val line: Int? = null,\n    val col: Int? = null,\n) {\n    override fun toString() = \"GradleError(line=$line, col=$col, file=$file, message='$message')\"\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/internal/GradleErrorCollector.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher.internal\n\nprivate enum class ErrorHeader(val message: String) {\n    FAILURE(\"FAILURE: \"),\n    WHERE(\"* Where:\"),\n    WHAT_WENT_WRONG(\"* What went wrong:\"),\n    TRY(\"* Try:\"),\n}\n\nprivate val errorHeaderValues = ErrorHeader.values()\n\nclass GradleErrorCollector {\n    private val _errors = mutableListOf<GradleError>()\n    val errors: List<GradleError> = _errors\n\n    private val sb = StringBuilder()\n    private var nextKey: ErrorHeader? = null\n    private val data = mutableMapOf<ErrorHeader, String>()\n\n    fun done() {\n        if (data.isNotEmpty()) {\n            val message = data[ErrorHeader.WHAT_WENT_WRONG] ?: \"Unknown error\"\n\n            _errors += data[ErrorHeader.WHERE]?.let { location ->\n                Regex(\"^Build file '(.+)' line: (\\\\d+)$\").matchEntire(location)?.let {\n                    GradleError(\n                        message = message,\n                        file = it.groupValues[1],\n                        line = it.groupValues[2].toInt(),\n                    )\n                }\n            } ?: GradleError(message)\n        }\n        data.clear()\n        sb.clear()\n    }\n\n    fun process(line: String) {\n        val str = line.trimEnd()\n        if (str.startsWith(ErrorHeader.FAILURE.message)) {\n            done()\n            data[ErrorHeader.FAILURE] = str.removePrefix(ErrorHeader.FAILURE.message)\n            return\n        }\n\n        if (str.startsWith(\"* Get more help\") ||\n            str.startsWith(\"BUILD FAILED \")\n        ) {\n            done()\n            nextKey = null\n            return\n        }\n\n        errorHeaderValues.firstOrNull { str.startsWith(it.message) }?.let {\n            nextKey?.let {\n                data[it] = sb.toString().trimEnd()\n            }\n            sb.clear()\n            nextKey = it\n            return\n        }\n\n        if (nextKey != null) {\n            sb.appendLine(line)\n        }\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsMain/kotlin/com/github/burrunan/launcher/internal/GradleOutErrorCollector.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher.internal\n\n// e: /../build.gradle.kts:62:1: Unresolved reference: invalid\nprivate val KOTLIN_COMPILE_ERROR = Regex(\"^e: (\\\\S.+?):(\\\\d+):(?:(\\\\d+):)? (.+)$\")\n// [ant:checkstyle] [ERROR] /.../SqlHopTableFunction.java:56:35: ',' is not followed by whitespace. [WhitespaceAfter]\nprivate val CHECKSTYLE_ERROR = Regex(\"^\\\\[ant:checkstyle\\\\] \\\\[ERROR\\\\] (\\\\S.+?):(\\\\d+):(?:(\\\\d+):)? (.+) \\\\[([^\\\\]]+)\\\\]\\$\")\n// /.../RelDataType.java:249: error: reference not found\nprivate val JAVA_ERROR = Regex(\"^(\\\\S.+?):(\\\\d+): error: (.+)$\")\n\nclass GradleOutErrorCollector {\n    private val _errors = mutableListOf<GradleError>()\n    val errors: List<GradleError> = _errors\n    private var taskName: String = \"Unknown task\"\n    private var javaError: MatchResult? = null\n    private val javaErrorLines = mutableListOf<String>()\n\n    fun process(line: String) {\n        if (line.startsWith(\"> Task \") ||\n            line.startsWith(\"> Configure\")\n        ) {\n            taskName = line.removePrefix(\"> \").let { \"[$it]\" }\n        }\n        if (line.startsWith(\"e: \")) {\n            // Looks like Kotlin error\n            // e: /../build.gradle.kts:62:1: Unresolved reference: invalid\n            KOTLIN_COMPILE_ERROR.matchEntire(line)?.let {\n                _errors += GradleError(\n                    message = \"$taskName ${it.groupValues[4]}\",\n                    file = it.groupValues[1],\n                    line = it.groupValues[2].toInt(),\n                    col = it.groupValues[3].takeIf { it.isNotBlank() }?.toInt(),\n                )\n            }\n            return\n        }\n        // Checkstyle error:\n        // [ant:checkstyle] [ERROR] /.../SqlHopTableFunction.java:56:35: ',' is not followed by whitespace. [WhitespaceAfter]\n        CHECKSTYLE_ERROR.matchEntire(line)?.let {\n            _errors += GradleError(\n                message = \"$taskName ${\"[${it.groupValues[5]}] \".removePrefix(\"[] \")}${it.groupValues[4]}\",\n                file = it.groupValues[1],\n                line = it.groupValues[2].toInt(),\n                col = it.groupValues[3].takeIf { it.isNotBlank() }?.toInt(),\n            )\n        }\n        processJavaError(line)\n    }\n\n    private fun processJavaError(line: String) {\n        // /.../RelDataType.java:249: error: reference not found\n        JAVA_ERROR.matchEntire(line)?.let {\n            done()\n            javaError = it\n            return\n        }\n        if (javaError != null) {\n            val errorContinuation = line.startsWith(\" \")\n            if (errorContinuation) {\n                javaErrorLines += line\n            }\n            if (!errorContinuation || javaErrorLines.size >= 3) {\n                done()\n            }\n        }\n    }\n\n    fun done() {\n        javaError?.let {\n            _errors += GradleError(\n                message = \"$taskName ${it.groupValues[3]}\\n${javaErrorLines.joinToString(\"\\n\")}\",\n                file = it.groupValues[1],\n                line = it.groupValues[2].toInt(),\n            )\n        }\n        javaError = null\n        javaErrorLines.clear()\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsTest/kotlin/com/github/burrunan/launcher/PropertiesParserTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass PropertiesParserTest {\n    @Test\n    fun simpleProperties() {\n        assertParse(\n            mapOf(\n                \"a-b\" to \"1\",\n                \"c\" to \"34 34\",\n                \"url\" to \"https://example.com\",\n            ),\n            \"\"\"\n            a-b=1\n            url=https\\://example.com\n            # asfd\n              c = 34 34\n\n            \"\"\".trimIndent(),\n        )\n    }\n\n    private fun assertParse(expected: Map<String, String>, value: String) {\n        assertEquals(\n            expected,\n            javaproperties.parseString(value).run {\n                getKeys().associateWith { get(it) }\n            },\n            value,\n        )\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsTest/kotlin/com/github/burrunan/launcher/RetrieveGradleVersionTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher\n\nimport actions.core.info\nimport actions.tool.cache.findAllVersions\nimport com.github.burrunan.test.runTest\nimport kotlin.test.Test\n\nclass RetrieveGradleVersionTest {\n    @Test\n    fun retrieve() = runTest {\n        for (version in GradleVersion.DYNAMIC_VERSIONS) {\n            val res = version.findUrl()\n            println(\"$version => $res\")\n        }\n    }\n\n    @Test\n    fun listTools() = runTest {\n        listTool(\"gradle\")\n        listTool(\"Gradle\")\n        listTool(\"mvn\")\n        listTool(\"Maven\")\n    }\n\n    private fun listTool(tool: String) {\n        info(\"All $tool versions: ${findAllVersions(tool).joinToString(\", \")}\")\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsTest/kotlin/com/github/burrunan/launcher/internal/GradleErrorCollectorTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher.internal\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass GradleErrorCollectorTest {\n    @Test\n    fun buildScriptFailure() {\n        testCollector(\n            \"\"\"\n                GradleError(line=62, col=null, file=/home/runner/work/pgjdbc/pgjdbc/build.gradle.kts, message='Script compilation errors:\n\n                  Line 62: invalid code here\n                           ^ Unresolved reference: invalid\n\n                  Line 62: invalid code here\n                                        ^ Unresolved reference: here\n\n                2 errors')\n            \"\"\".trimIndent(),\n            \"\"\"\n                * Where:\n                Build file '/home/runner/work/pgjdbc/pgjdbc/build.gradle.kts' line: 62\n\n                * What went wrong:\n                Script compilation errors:\n\n                  Line 62: invalid code here\n                           ^ Unresolved reference: invalid\n\n                  Line 62: invalid code here\n                                        ^ Unresolved reference: here\n\n                2 errors\n\n                * Try:\n                Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.\n\n                * Get more help at https://help.gradle.org\n\n                BUILD FAILED in 44s\n            \"\"\".trimIndent(),\n        )\n    }\n\n    @Test\n    fun noLocation() {\n        testCollector(\n            \"\"\"\n                GradleError(line=null, col=null, file=null, message='Task 'asdfasdf' not found in root project 'pgjdbc'.')\n            \"\"\".trimIndent(),\n            \"\"\"\n                See https://docs.gradle.org/6.3/userguide/command_line_interface.html#sec:command_line_warnings\n\n                FAILURE: Build failed with an exception.\n\n                * What went wrong:\n                Task 'asdfasdf' not found in root project 'pgjdbc'.\n\n                * Try:\n                Run gradle tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.\n\n                * Get more help at https://help.gradle.org\n\n                BUILD FAILED in 37s\n            \"\"\".trimIndent(),\n        )\n    }\n\n    private fun testCollector(expected: String, input: String) {\n        val collector = GradleErrorCollector()\n        input.lines().forEach { collector.process(it) }\n\n        collector.done()\n\n        assertEquals(expected, collector.errors.joinToString(\"\\n\"))\n    }\n}\n"
  },
  {
    "path": "gradle-launcher/src/jsTest/kotlin/com/github/burrunan/launcher/internal/GradleOutCollectorTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.launcher.internal\n\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass GradleOutCollectorTest {\n    @Test\n    fun koltlinCompileErrors() {\n        testCollector(\n            \"\"\"\n                GradleError(line=62, col=1, file=/home/runner/work/pgjdbc/pgjdbc/build.gradle.kts, message='[Configure project :] Unresolved reference: invalid')\n                GradleError(line=62, col=14, file=/home/runner/work/pgjdbc/pgjdbc/build.gradle.kts, message='[Configure project :] Unresolved reference: here')\n            \"\"\".trimIndent(),\n            \"\"\"\n                > Configure project :\n                Evaluating root project 'pgjdbc' using build file '/home/runner/work/pgjdbc/pgjdbc/build.gradle.kts'.\n                Loading cache entry 'cache/eila5i6e0q7sxpvg89w345ymz' from S3 bucket\n                e: /home/runner/work/pgjdbc/pgjdbc/build.gradle.kts:62:1: Unresolved reference: invalid\n                e: /home/runner/work/pgjdbc/pgjdbc/build.gradle.kts:62:14: Unresolved reference: here\n            \"\"\".trimIndent(),\n        )\n    }\n\n    @Test\n    fun checkstyleError() {\n        testCollector(\n            \"\"\"\n                GradleError(line=56, col=35, file=/Users/runner/work/calcite/calcite/core/src/main/java/org/apache/calcite/sql/SqlHopTableFunction.java, message='[Task :core:checkstyleMain] [WhitespaceAfter] ',' is not followed by whitespace.')\n                GradleError(line=32, col=null, file=/code/calcite/linq4j/src/main/java/org/apache/calcite/linq4j/AbstractEnumerable.java, message='[Task :core:checkstyleMain] [Indentation] 'method def modifier' has incorrect indentation level 0, expected level should be 2.')\n            \"\"\".trimIndent(),\n            \"\"\"\n                > Task :core:checkstyleMain\n                [ant:checkstyle] [ERROR] /Users/runner/work/calcite/calcite/core/src/main/java/org/apache/calcite/sql/SqlHopTableFunction.java:56:35: ',' is not followed by whitespace. [WhitespaceAfter]\n                [ant:checkstyle] [ERROR] /code/calcite/linq4j/src/main/java/org/apache/calcite/linq4j/AbstractEnumerable.java:32: 'method def modifier' has incorrect indentation level 0, expected level should be 2. [Indentation]\n            \"\"\".trimIndent(),\n        )\n    }\n\n    @Test\n    fun javadocError() {\n        testCollector(\n            \"\"\"\n                GradleError(line=249, col=null, file=/Users/../type/RelDataType.java, message='[Task :babel:javadoc] reference not found\n                   * {@link #equals(Object)}.\n                            ^')\n            \"\"\".trimIndent(),\n            \"\"\"\n                > Task :babel:javadoc\n                /Users/runner/runners/2.263.0/work/calcite/calcite/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java:632: warning: no @param for rel\n                  public List<Double> getAverageColumnSizesNotNull(RelNode rel) {\n                                      ^\n                /Users/runner/runners/2.263.0/work/calcite/calcite/core/src/main/java/org/apache/calcite/rel/metadata/RelMetadataQuery.java:632: warning: no @return\n                  public List<Double> getAverageColumnSizesNotNull(RelNode rel) {\n                                      ^\n                /Users/../type/RelDataType.java:249: error: reference not found\n                   * {@link #equals(Object)}.\n                            ^\n            \"\"\".trimIndent(),\n        )\n    }\n\n    @Test\n    fun javacError() {\n        testCollector(\n            \"\"\"\n                GradleError(line=46, col=null, file=/home/runner/../ReaderInputStreamTest.java, message='[Task :compileJava] cannot find symbol\n                    Arrays.fill(acutal, (byte) 0x00);\n                                ^\n                  symbol:   variable acutal')\n            \"\"\".trimIndent(),\n            \"\"\"\n                > Task :compileJava\n                Compiling with JDK Java compiler API.\n                /home/runner/../ReaderInputStreamTest.java:46: error: cannot find symbol\n                    Arrays.fill(acutal, (byte) 0x00);\n                                ^\n                  symbol:   variable acutal\n                  location: class ReaderInputStreamTest\n                Note: Some input files use or override a deprecated API.\n                Note: Recompile with -Xlint:deprecation for details.\n            \"\"\".trimIndent(),\n        )\n    }\n\n    private fun testCollector(expected: String, input: String) {\n        val collector = GradleOutErrorCollector()\n        input.lines().forEach { collector.process(it) }\n\n        collector.done()\n\n        assertEquals(expected, collector.errors.joinToString(\"\\n\"))\n    }\n}\n"
  },
  {
    "path": "gradle.properties",
    "content": "#\n# Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\norg.gradle.parallel=true\n\nkotlin.daemon.jvmargs=-Xmx1500m\nkotlin.parallel.tasks.in.project=true\n\nkotlin.code.style=official\n"
  },
  {
    "path": "gradlew",
    "content": "#!/bin/sh\n\n#\n# Copyright © 2015-2021 the original authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n# SPDX-License-Identifier: Apache-2.0\n#\n\n##############################################################################\n#\n#   Gradle start up script for POSIX generated by Gradle.\n#\n#   Important for running:\n#\n#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is\n#       noncompliant, but you have some other compliant shell such as ksh or\n#       bash, then to run this script, type that shell name before the whole\n#       command line, like:\n#\n#           ksh Gradle\n#\n#       Busybox and similar reduced shells will NOT work, because this script\n#       requires all of these POSIX shell features:\n#         * functions;\n#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,\n#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;\n#         * compound commands having a testable exit status, especially «case»;\n#         * various built-in commands including «command», «set», and «ulimit».\n#\n#   Important for patching:\n#\n#   (2) This script targets any POSIX shell, so it avoids extensions provided\n#       by Bash, Ksh, etc; in particular arrays are avoided.\n#\n#       The \"traditional\" practice of packing multiple parameters into a\n#       space-separated string is a well documented source of bugs and security\n#       problems, so this is (mostly) avoided, by progressively accumulating\n#       options in \"$@\", and eventually passing that to Java.\n#\n#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,\n#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;\n#       see the in-line comments for details.\n#\n#       There are tweaks for specific operating systems such as AIX, CygWin,\n#       Darwin, MinGW, and NonStop.\n#\n#   (3) This script is generated from the Groovy template\n#       https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt\n#       within the Gradle project.\n#\n#       You can find Gradle at https://github.com/gradle/gradle/.\n#\n##############################################################################\n\n# Attempt to set APP_HOME\n\n# Resolve links: $0 may be a link\napp_path=$0\n\n# Need this for daisy-chained symlinks.\nwhile\n    APP_HOME=${app_path%\"${app_path##*/}\"}  # leaves a trailing /; empty if no leading path\n    [ -h \"$app_path\" ]\ndo\n    ls=$( ls -ld \"$app_path\" )\n    link=${ls#*' -> '}\n    case $link in             #(\n      /*)   app_path=$link ;; #(\n      *)    app_path=$APP_HOME$link ;;\n    esac\ndone\n\n# This is normally unused\n# shellcheck disable=SC2034\nAPP_BASE_NAME=${0##*/}\n# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)\nAPP_HOME=$( cd -P \"${APP_HOME:-./}\" > /dev/null && printf '%s\\n' \"$PWD\" ) || exit\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=maximum\n\nwarn () {\n    echo \"$*\"\n} >&2\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n} >&2\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"$( uname )\" in                #(\n  CYGWIN* )         cygwin=true  ;; #(\n  Darwin* )         darwin=true  ;; #(\n  MSYS* | MINGW* )  msys=true    ;; #(\n  NONSTOP* )        nonstop=true ;;\nesac\n\nCLASSPATH=\"\\\\\\\"\\\\\\\"\"\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=$JAVA_HOME/jre/sh/java\n    else\n        JAVACMD=$JAVA_HOME/bin/java\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=java\n    if ! command -v java >/dev/null 2>&1\n    then\n        die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nfi\n\n# Increase the maximum file descriptors if we can.\nif ! \"$cygwin\" && ! \"$darwin\" && ! \"$nonstop\" ; then\n    case $MAX_FD in #(\n      max*)\n        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        MAX_FD=$( ulimit -H -n ) ||\n            warn \"Could not query maximum file descriptor limit\"\n    esac\n    case $MAX_FD in  #(\n      '' | soft) :;; #(\n      *)\n        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.\n        # shellcheck disable=SC2039,SC3045\n        ulimit -n \"$MAX_FD\" ||\n            warn \"Could not set maximum file descriptor limit to $MAX_FD\"\n    esac\nfi\n\n# Collect all arguments for the java command, stacking in reverse order:\n#   * args from the command line\n#   * the main class name\n#   * -classpath\n#   * -D...appname settings\n#   * --module-path (only if needed)\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif \"$cygwin\" || \"$msys\" ; then\n    APP_HOME=$( cygpath --path --mixed \"$APP_HOME\" )\n    CLASSPATH=$( cygpath --path --mixed \"$CLASSPATH\" )\n\n    JAVACMD=$( cygpath --unix \"$JAVACMD\" )\n\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    for arg do\n        if\n            case $arg in                                #(\n              -*)   false ;;                            # don't mess with options #(\n              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath\n                    [ -e \"$t\" ] ;;                      #(\n              *)    false ;;\n            esac\n        then\n            arg=$( cygpath --path --ignore --mixed \"$arg\" )\n        fi\n        # Roll the args list around exactly as many times as the number of\n        # args, so each arg winds up back in the position where it started, but\n        # possibly modified.\n        #\n        # NB: a `for` loop captures its iteration list before it begins, so\n        # changing the positional parameters here affects neither the number of\n        # iterations, nor the values presented in `arg`.\n        shift                   # remove old arg\n        set -- \"$@\" \"$arg\"      # push replacement arg\n    done\nfi\n\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Collect all arguments for the java command:\n#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,\n#     and any embedded shellness will be escaped.\n#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be\n#     treated as '${Hostname}' itself on the command line.\n\nset -- \\\n        \"-Dorg.gradle.appname=$APP_BASE_NAME\" \\\n        -classpath \"$CLASSPATH\" \\\n        -jar \"$APP_HOME/gradle/wrapper/gradle-wrapper.jar\" \\\n        \"$@\"\n\n# Stop when \"xargs\" is not available.\nif ! command -v xargs >/dev/null 2>&1\nthen\n    die \"xargs is not available\"\nfi\n\n# Use \"xargs\" to parse quoted args.\n#\n# With -n1 it outputs one arg per line, with the quotes and backslashes removed.\n#\n# In Bash we could simply go:\n#\n#   readarray ARGS < <( xargs -n1 <<<\"$var\" ) &&\n#   set -- \"${ARGS[@]}\" \"$@\"\n#\n# but POSIX shell has neither arrays nor command substitution, so instead we\n# post-process each arg (as a line of input to sed) to backslash-escape any\n# character that might be a shell metacharacter, then use eval to reverse\n# that process (while maintaining the separation between arguments), and wrap\n# the whole thing up as a single \"set\" statement.\n#\n# This will of course break if any of these variables contains a newline or\n# an unmatched quote.\n#\n\neval \"set -- $(\n        printf '%s\\n' \"$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\" |\n        xargs -n1 |\n        sed ' s~[^-[:alnum:]+,./:=@_]~\\\\&~g; ' |\n        tr '\\n' ' '\n    )\" '\"$@\"'\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n@rem SPDX-License-Identifier: Apache-2.0\r\n@rem\r\n\r\n@if \"%DEBUG%\"==\"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\"==\"\" set DIRNAME=.\r\n@rem This is normally unused\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif %ERRORLEVEL% equ 0 goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto execute\r\n\r\necho. 1>&2\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2\r\necho. 1>&2\r\necho Please set the JAVA_HOME variable in your environment to match the 1>&2\r\necho location of your Java installation. 1>&2\r\n\r\ngoto fail\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" -jar \"%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\" %*\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif %ERRORLEVEL% equ 0 goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nset EXIT_CODE=%ERRORLEVEL%\r\nif %EXIT_CODE% equ 0 set EXIT_CODE=1\r\nif not \"\"==\"%GRADLE_EXIT_CONSOLE%\" exit %EXIT_CODE%\r\nexit /b %EXIT_CODE%\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "hashing/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nplugins {\n    kotlin(\"plugin.serialization\")\n}\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                implementation(projects.wrappers.actionsToolkit)\n                implementation(projects.wrappers.js)\n                implementation(projects.wrappers.nodejs)\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-core\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "hashing/src/jsMain/kotlin/com/github/burrunan/hashing/HashDetails.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.hashing\n\nimport actions.core.ActionFailedException\nimport actions.core.warning\nimport com.github.burrunan.wrappers.nodejs.normalizedPath\nimport com.github.burrunan.wrappers.nodejs.pipeAndWait\nimport js.promise.await\nimport kotlinx.serialization.Serializable\nimport node.crypto.BinaryToTextEncoding\nimport node.crypto.createHash\nimport node.fs.createReadStream\nimport node.fs.stat\nimport node.process.process\n\n@Serializable\nclass HashDetails(\n    val info: HashInfo,\n    val contents: HashContents,\n)\n\n@Serializable\nclass HashInfo(\n    val totalBytes: Long,\n    val hash: String,\n    val totalFiles: Int,\n)\n\n@Serializable\nclass HashContents(\n    val files: Map<String, FileDetails>,\n)\n\n@Serializable\nclass FileDetails(\n    val fileSize: Long,\n    val hash: String,\n)\n\n/**\n * Sample: ~/.gradle/caches/modules-2/files-2.1/com.google.errorprone/error_prone_annotations/2.0.18/5f65affce1684999e2f4024983835efc3504012e/error_prone_annotations-2.0.18.jar\n */\nprivate fun sha1FromModulesFileName(key: String): String {\n    val lastSlash = key.lastIndexOf('/')\n    val hashStart = key.lastIndexOf('/', startIndex = lastSlash - 1) + 1\n    return key.substring(hashStart, lastSlash).padStart(40, '0')\n}\n\nsuspend fun hashFilesDetailed(\n    vararg paths: String,\n    algorithm: String = \"sha1\",\n    includeFileName: Boolean = true,\n): HashDetails = try {\n    val globber = actions.glob.create(paths.joinToString(\"\\n\"))\n    val fileNames = globber.glob().await()\n    // Sorting is needed for stable overall hash\n    fileNames.sort()\n\n    val githubWorkspace = process.cwd()\n    val homeDir = \"~\".normalizedPath\n\n    var totalBytes = 0L\n    val files = mutableMapOf<String, FileDetails>()\n    val overallHash = createHash(algorithm)\n    for (name in fileNames) {\n        val statSync = stat(name)\n        if (statSync.isDirectory()) {\n            continue\n        }\n        val fileSize = statSync.size.toLong()\n        totalBytes += fileSize\n        val key = when {\n            name.startsWith(githubWorkspace) ->\n                \"ws://\" + name.substring(githubWorkspace.length)\n            name.startsWith(homeDir) ->\n                \"~\" + name.substring(homeDir.length)\n            else -> name\n        }.replace('\\\\', '/')\n        // Avoid hashing the contents when we know the hash from the file path\n        val digest = when {\n            algorithm == \"sha1\" && key.startsWith(\"~/.gradle/caches/modules-2/files-2.1/\") ->\n                sha1FromModulesFileName(key)\n            key.startsWith(\"~/.gradle/caches/build-cache-1/\") ->\n                key.substringAfterLast('/')\n            else -> {\n                val hash = createHash(algorithm)\n                try {\n                    createReadStream(name).pipeAndWait(hash, end = true)\n                } catch (e: Throwable) {\n                    warning(\"Unable to hash $name, will ignore the file: ${e.stackTraceToString()}\")\n                    continue\n                }\n                hash.digest(BinaryToTextEncoding.hex)\n            }\n        }\n        files[key] = FileDetails(fileSize, digest)\n        // Add filename\n        if (includeFileName) {\n            overallHash.update(key)\n        }\n        overallHash.update(digest)\n    }\n    HashDetails(\n        HashInfo(totalBytes, overallHash.digest(BinaryToTextEncoding.hex), files.size),\n        HashContents(files),\n    )\n} catch (e: Throwable) {\n    throw ActionFailedException(\"Unable to hash ${paths.joinToString(\", \")}: $e\", e)\n}\n"
  },
  {
    "path": "hashing/src/jsMain/kotlin/com/github/burrunan/hashing/diff.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.hashing\n\nimport com.github.burrunan.formatBytes\n\nclass Diff(\n    val newFiles: Int,\n    val totalUpdated: Long,\n    val totalDeleted: Long,\n    val messages: List<String>,\n    val updatedFiles: List<String>,\n    val deletedFiles: List<String>,\n) {\n    val summary: String\n        get() =\n            (if (updatedFiles.isNotEmpty()) \"${updatedFiles.size} updates (${totalUpdated.formatBytes()})\" else \"\") +\n                (if (deletedFiles.isNotEmpty()) (if (updatedFiles.isNotEmpty()) \", \" else \"\") +\n                    \"${deletedFiles.size} deletes (${totalDeleted.formatBytes()})\" else \"\") +\n                \"\\n  \" + messages.joinToString(\"\\n  \")\n}\n\nfun diff(\n    oldContents: HashContents,\n    newContents: HashContents,\n    maxUpdatesToPrint: Int = 50,\n): Diff {\n    val messages = mutableListOf<String>()\n    val updatedFiles = mutableListOf<String>()\n    val deletedFiles = mutableListOf<String>()\n    var newFiles = 0\n    var totalUpdated = 0L\n    var totalDeleted = 0L\n    for ((file, hash) in newContents.files) {\n        val oldHash = oldContents.files[file]\n        if (oldHash?.hash == hash.hash) {\n            continue\n        }\n        updatedFiles.add(file)\n        if (messages.size >= maxUpdatesToPrint) {\n            continue\n        }\n        messages.add(\n            if (oldHash == null) {\n                newFiles += 1\n                totalUpdated += hash.fileSize\n                \"N ${hash.fileSize} $file ${hash.hash}\"\n            } else {\n                totalUpdated += hash.fileSize\n                \"U ${hash.fileSize} $file ${oldHash.fileSize} ${oldHash.hash} => ${hash.hash}\"\n            },\n        )\n    }\n    if (oldContents.files.size + newFiles != newContents.files.size) {\n        for ((file, hash) in oldContents.files) {\n            if (file !in newContents.files) {\n                deletedFiles.add(file)\n                totalDeleted += hash.fileSize\n                if (messages.size < maxUpdatesToPrint) {\n                    messages.add(\"D $file $hash\")\n                }\n            }\n        }\n    }\n    return Diff(\n        newFiles = newFiles,\n        totalUpdated = totalUpdated,\n        totalDeleted = totalDeleted,\n        messages = messages,\n        updatedFiles = updatedFiles,\n        deletedFiles = deletedFiles,\n    )\n}\n"
  },
  {
    "path": "hashing/src/jsMain/kotlin/com/github/burrunan/hashing/hashFiles.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.hashing\n\nimport actions.core.ActionFailedException\nimport actions.core.warning\nimport com.github.burrunan.wrappers.nodejs.normalizedPath\nimport com.github.burrunan.wrappers.nodejs.pipeAndWait\nimport js.promise.await\nimport node.WritableStream\nimport node.buffer.BufferEncoding\nimport node.crypto.BinaryToTextEncoding\nimport node.crypto.createHash\nimport node.fs.createReadStream\nimport node.fs.stat\nimport node.process.process\n\ndata class HashResult(\n    val hash: String,\n    val numFiles: Int,\n    val totalBytes: Int,\n)\n\nsuspend fun hashFiles(\n    vararg paths: String,\n    algorithm: String = \"sha1\",\n    includeFileName: Boolean = true,\n): HashResult = try {\n    val globber = actions.glob.create(paths.joinToString(\"\\n\"))\n    val fileNames = globber.glob().await()\n    fileNames.sort()\n\n    val githubWorkspace = process.cwd()\n    val homeDir = \"~\".normalizedPath\n    val hash = createHash(algorithm)\n\n    var totalBytes = 0\n    var numFiles = 0\n    for (name in fileNames) {\n        val statSync = stat(name)\n        if (statSync.isDirectory()) {\n            continue\n        }\n        val key = when {\n            name.startsWith(githubWorkspace) ->\n                \"ws://\" + name.substring(githubWorkspace.length)\n            name.startsWith(homeDir) ->\n                \"~\" + name.substring(homeDir.length)\n            else -> name\n        }.replace('\\\\', '/')\n\n        numFiles += 1\n        totalBytes += statSync.size.toInt()\n        // Add filename\n\n        try {\n            createReadStream(name).pipeAndWait(hash, end = false)\n        } catch (e: Throwable) {\n            warning(\"Unable to hash $name, will ignore the file: ${e.stackTraceToString()}\")\n            continue\n        }\n\n        if (includeFileName) {\n            hash.update(key, BufferEncoding.utf8)\n        }\n    }\n    hash.unsafeCast<WritableStream>().end()\n    HashResult(\n        hash = hash.digest(BinaryToTextEncoding.hex),\n        numFiles = numFiles,\n        totalBytes = totalBytes,\n    )\n} catch (e: Throwable) {\n    throw ActionFailedException(\"Unable to hash ${paths.joinToString(\", \")}: $e\", e)\n}\n"
  },
  {
    "path": "layered-cache/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nplugins {\n    kotlin(\"plugin.serialization\")\n}\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                implementation(projects.gradleLauncher)\n                implementation(projects.hashing)\n                implementation(projects.wrappers.actionsCache)\n                implementation(projects.wrappers.actionsToolkit)\n                implementation(projects.wrappers.nodejs)\n                implementation(projects.wrappers.octokitWebhooks)\n                implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-core\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-serialization-json\")\n            }\n        }\n        jsTest {\n            dependencies {\n                implementation(projects.cacheServiceMock)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/GradleCacheAction.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle\n\nimport actions.core.ActionFailedException\nimport actions.core.ActionStage\nimport actions.core.info\nimport actions.exec.exec\nimport com.github.burrunan.gradle.cache.*\nimport com.github.burrunan.gradle.github.suspendingStateVariable\nimport com.github.burrunan.launcher.GradleDistribution\nimport octokit.ActionsTrigger\nimport kotlin.js.Date\nimport kotlin.math.roundToInt\n\nclass GradleCacheAction(\n    val trigger: ActionsTrigger,\n    val params: Parameters,\n    val gradleDistribution: GradleDistribution,\n) {\n    companion object {\n        const val DEFAULT_BRANCH_VAR = \"defaultbranch\"\n    }\n\n    private val treeId = suspendingStateVariable(\"tree_id\") {\n        // Sometimes the output might include a newline, so trim it\n        // See https://github.com/burrunan/gradle-cache-action/issues/63\n        exec(\"git\", \"log\", \"-1\", \"--quiet\", \"--format=%T\", captureOutput = true).stdout.trim()\n    }\n\n    suspend fun execute(stage: ActionStage) {\n        val gradleVersion = gradleDistribution.version\n\n        val caches = mutableListOf<Cache>()\n\n        if (params.generatedGradleJars) {\n            caches.add(gradleGeneratedJarsCache(gradleVersion))\n        }\n\n        if (params.localBuildCache) {\n            caches.add(localBuildCache(params.jobId, trigger, gradleVersion, treeId.get()))\n        }\n\n        if (params.gradleDependenciesCache) {\n            caches.add(gradleDependenciesCache(trigger, params.path, params.gradleDependenciesCacheKey))\n        }\n\n        if (params.mavenDependenciesCache) {\n            caches.add(mavenDependenciesCache(trigger, params.path, params.mavenLocalIgnorePaths))\n        }\n\n        val cache = CompositeCache(\"all-caches\", caches, concurrent = params.concurrent)\n        when (stage) {\n            ActionStage.MAIN -> {\n                val started = Date.now()\n                val restore = cache.restore()\n                val elapsed = Date.now() - started\n                info(\"Cache restore took ${(elapsed / 1000).roundToInt()} seconds\")\n            }\n            ActionStage.POST -> {\n                if (params.readOnly) {\n                    info(\"read-only == true, so will skip cache upload\")\n                } else {\n                    cache.save()\n                }\n            }\n            else -> throw ActionFailedException(\"Cache action should be called in PRE or POST stages only. \" +\n                \"Current stage is $stage\")\n        }\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/Parameters.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle\n\ndata class Parameters(\n    val jobId: String,\n    val path: String,\n    val debug: Boolean,\n    val generatedGradleJars: Boolean,\n    val localBuildCache: Boolean,\n    val gradleDependenciesCache: Boolean,\n    val gradleDependenciesCacheKey: List<String>,\n    val mavenDependenciesCache: Boolean,\n    val mavenLocalIgnorePaths: List<String>,\n    val concurrent: Boolean,\n    val readOnly: Boolean,\n)\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/ActionsTriggerExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.gradle.cache\n\nimport actions.core.ActionsEnvironment\nimport com.github.burrunan.gradle.GradleCacheAction\nimport octokit.ActionsTrigger\n\nval ActionsTrigger.cacheKey: String\n    get() = when (this) {\n        is ActionsTrigger.PullRequest -> \"PR${event.pull_request.number}\"\n        is ActionsTrigger.BranchPush -> when (val ref = event.ref.removePrefix(\"refs/heads/\")) {\n            event.repository.default_branch.removePrefix(\"refs/heads/\") ->\n                GradleCacheAction.DEFAULT_BRANCH_VAR\n            else -> ref\n        }\n        is ActionsTrigger.Schedule, is ActionsTrigger.WorkflowDispatch ->\n            GradleCacheAction.DEFAULT_BRANCH_VAR\n        is ActionsTrigger.Other -> \"$name-${ActionsEnvironment.GITHUB_WORKFLOW}-${ActionsEnvironment.GITHUB_SHA}\"\n    }\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/Cache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport actions.cache.RestoreType\n\ninterface Cache {\n    val name: String\n\n    suspend fun save()\n    suspend fun restore(): RestoreType\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/CompositeCache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport actions.cache.RestoreType\nimport actions.core.ext.group\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.supervisorScope\n\nclass CompositeCache(\n    override val name: String,\n    private val caches: List<Cache>,\n    private val concurrent: Boolean,\n) : Cache {\n    override suspend fun save() {\n        if (!concurrent) {\n            for (cache in caches) {\n                group(\"Save ${cache.name}\") {\n                    cache.save()\n                }\n            }\n            return\n        }\n\n        supervisorScope {\n            for (cache in caches) {\n                launch {\n                    cache.save()\n                }\n            }\n        }\n    }\n\n    override suspend fun restore(): RestoreType {\n        if (!concurrent) {\n            for (cache in caches) {\n                group(\"Restore ${cache.name}\") {\n                    cache.restore()\n                }\n            }\n            return RestoreType.Unknown\n        }\n\n        supervisorScope {\n            for (cache in caches) {\n                launch {\n                    cache.restore()\n                }\n            }\n        }\n        return RestoreType.Unknown\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/DefaultCache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport actions.cache.RestoreType\nimport actions.cache.restoreAndLog\nimport actions.cache.saveAndLog\nimport actions.core.debug\nimport actions.core.info\nimport actions.glob.removeFiles\nimport com.github.burrunan.formatBytes\nimport com.github.burrunan.gradle.github.stateVariable\nimport com.github.burrunan.gradle.github.toBoolean\nimport com.github.burrunan.gradle.github.toInt\nimport com.github.burrunan.hashing.HashContents\nimport com.github.burrunan.hashing.HashDetails\nimport com.github.burrunan.hashing.HashInfo\nimport com.github.burrunan.hashing.hashFilesDetailed\nimport com.github.burrunan.wrappers.nodejs.exists\nimport kotlin.math.absoluteValue\n\nclass DefaultCache(\n    name: String,\n    val primaryKey: String,\n    private val restoreKeys: List<String> = listOf(),\n    private val paths: List<String>,\n    private val readOnlyMessage: String? = null,\n    stateKey: String = \"\",\n    private val skipRestoreIfPathExists: String? = null\n) : Cache {\n    @Suppress(\"CanBePrimaryConstructorProperty\")\n    override val name: String = name\n\n    private val version = \"1-\"\n\n    private val cacheInfo =\n        MetadataFile(\"$name-info\", HashInfo.serializer())\n    private val cacheContents =\n        MetadataFile(\"$name-contents\", HashContents.serializer())\n    private val saveRestorePaths = paths + cacheInfo.cachedName + cacheContents.cachedName\n\n    private val isExactMatch = stateVariable(\"${name}_${stateKey}_exact\").toBoolean()\n    private val isSkipped = stateVariable(\"${name}_${stateKey}_skip\").toBoolean()\n    private val restoredKeyIndex = stateVariable(\"${name}_${stateKey}_key\").toInt(-1)\n\n    private val restoredKey: String?\n        get() = when {\n            isExactMatch.get() -> primaryKey\n            restoredKeyIndex.get() >= 0 -> restoreKeys[restoredKeyIndex.get()]\n            else -> null\n        }\n\n    private var details: HashDetails? = null\n\n    suspend fun info(): HashInfo? {\n        details?.info?.let { return it }\n        restoredKey?.let { cacheContents.prepare(it) }\n        if (!isExactMatch.get() && restoredKeyIndex.get() == -1) {\n            // Cache was not restored => no information known\n            return null\n        }\n        return cacheInfo.decode()\n    }\n\n    suspend fun contents(): HashContents? {\n        details?.contents?.let { return it }\n        restoredKey?.let { cacheContents.prepare(it) }\n        if (!isExactMatch.get() && restoredKeyIndex.get() == -1) {\n            // Cache was not restored => no information known\n            return null\n        }\n        return cacheContents.decode()\n    }\n\n    override suspend fun restore(): RestoreType {\n        skipRestoreIfPathExists?.let {\n            if (exists(it)) {\n                debug { \"$name: $it already exists, so the cache restore and upload will be skipped\" }\n                isSkipped.set(true)\n            }\n        }\n        debug { \"$name: restoring $primaryKey, $restoreKeys, $saveRestorePaths\" }\n        return restoreAndLog(saveRestorePaths, primaryKey, restoreKeys, version = version).also {\n            isExactMatch.set(it is RestoreType.Exact)\n            restoredKeyIndex.set(\n                when (it) {\n                    is RestoreType.Partial -> restoreKeys.indexOfFirst { key -> it.path.startsWith(key) }\n                    else -> -1\n                },\n            )\n            debug { \"$name: restore type $it, ${isExactMatch.get()}, ${restoredKeyIndex.get()}\" }\n\n            restoredKey?.let { key ->\n                cacheInfo.restore(key)\n                cacheContents.restore(key)\n            }\n        }\n    }\n\n    override suspend fun save() {\n        debug { \"$name: saving ${isExactMatch.get()} ${restoredKeyIndex.get()} $primaryKey, $restoreKeys, $saveRestorePaths\" }\n        if (isSkipped.get()) {\n            debug { \"$name: cache save skipped\" }\n            return\n        }\n        if (isExactMatch.get()) {\n            info(\"$name loaded from exact match, no need to update the cache entry\")\n            return\n        }\n        readOnlyMessage?.let {\n            info(\"$name is configured as read-only: $it\")\n            return\n        }\n\n        restoredKey?.let { key ->\n            cacheInfo.prepare(key)\n            cacheContents.prepare(key)\n        }\n\n        val oldHash = info()\n\n        val newHash = hashFilesDetailed(*paths.toTypedArray())\n        details = newHash\n\n        if (newHash.contents.files.isEmpty()) {\n            info(\"$name: no files to cache => won't upload empty cache\")\n            return\n        }\n        if (oldHash != null) {\n            info(\"$name: comparing modifications of the cache contents\")\n            if (newHash.info.hash == oldHash.hash) {\n                info(\"$name: contents did not change => no need to upload it\")\n                return\n            }\n            val delta = newHash.info.totalBytes - oldHash.totalBytes\n            info(\"$name: hash content differs (${delta.absoluteValue} bytes ${if (delta >= 0) \"increase\" else \"decrease\"})\")\n        }\n        info(\"$name: uploading ${newHash.info.totalBytes.formatBytes()}, ${newHash.contents.files.size} files as $primaryKey\")\n        cacheInfo.encode(newHash.info)\n        cacheContents.encode(newHash.contents)\n        saveAndLog(saveRestorePaths, primaryKey, version = version)\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/GradleGeneratedJarsCache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nfun gradleGeneratedJarsCache(gradleVersion: String): Cache =\n    DefaultCache(\n        name = \"gradle-generated-jars\",\n        primaryKey = \"generated-gradle-jars-gradle-$gradleVersion\",\n        paths = listOf(\n            \"~/.gradle/caches/$gradleVersion/generated-gradle-jars/*\",\n            \"!~/.gradle/caches/$gradleVersion/generated-gradle-jars/*.lock\",\n        ),\n        skipRestoreIfPathExists = \"~/.gradle/caches/$gradleVersion/generated-gradle-jars\",\n    )\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/LayeredCache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport actions.cache.RestoreType\nimport actions.core.ActionFailedException\nimport actions.core.debug\nimport actions.core.info\nimport actions.core.warning\nimport actions.glob.removeFiles\nimport com.github.burrunan.formatBytes\nimport com.github.burrunan.gradle.github.stateVariable\nimport com.github.burrunan.gradle.github.toBoolean\nimport com.github.burrunan.hashing.*\nimport kotlinx.serialization.Serializable\n\n@Serializable\nclass CacheLayers(\n    val layers: List<CacheLayer>,\n    val deletedFiles: List<String>,\n)\n\n@Serializable\nclass CacheLayer(\n    // format is $version-...\n    val primaryKey: String,\n    val paths: List<String>,\n)\n\nclass LayeredCache(\n    override val name: String,\n    private val baseline: String,\n    val maxLayers: Int = 5,\n    private val primaryKey: String,\n    private val restoreKeys: List<String> = listOf(),\n    private val paths: List<String>,\n) : Cache {\n    private val version = \"1\"\n\n    private val layers = MetadataFile(\"layer-$name\", CacheLayers.serializer())\n\n    private val isExactMatch = stateVariable(\"${name}_exact\").toBoolean()\n\n    private val index = DefaultCache(\n        name = \"$version-index-$name\",\n        primaryKey = \"$version-index-$primaryKey\",\n        restoreKeys = restoreKeys.map { \"$version-index-$it\" },\n        paths = listOf(layers.cachedName),\n    )\n\n    override fun toString(): String =\n        \"Cache $name, primaryKey=$primaryKey, restoreKeys=$restoreKeys, \"\n\n    private fun CacheLayer.toCache(stateKey: String) =\n        DefaultCache(\n            name = name,\n            stateKey = stateKey,\n            primaryKey = primaryKey,\n            restoreKeys = if (paths.isNotEmpty()) listOf() else restoreKeys.map { \"$version-$it\" },\n            paths = this@toCache.paths.ifEmpty { this@LayeredCache.paths },\n        )\n\n    private fun Diff.toLayer(): CacheLayer {\n        // @actions/cache treats \"paths\" as a part of the cache key, so \"delta-\" is not important here for correctness\n        // delta- is here for readability\n        return CacheLayer(\n            primaryKey = \"$version-delta-$primaryKey\",\n            paths = updatedFiles,\n        )\n    }\n\n    override suspend fun restore(): RestoreType {\n        val indexRestoreType = index.restore()\n        if (indexRestoreType == RestoreType.None) {\n            return RestoreType.None\n        }\n        val cacheIndex = layers.decode() ?: run {\n            warning(\"Unable to restore cache $this\")\n            return RestoreType.Unknown\n        }\n\n        var restoreType: RestoreType = when (indexRestoreType) {\n            is RestoreType.Exact -> RestoreType.Exact(indexRestoreType.path.removePrefix(\"$version-index-\"))\n            is RestoreType.Partial -> RestoreType.Partial(indexRestoreType.path.removePrefix(\"$version-index-\"))\n            else -> indexRestoreType\n        }\n\n        info(\n            cacheIndex.layers.joinToString(\", \", \"$name: ${cacheIndex.layers.size} layers. \") {\n                if (it.paths.isEmpty()) it.primaryKey else \"${it.primaryKey} (${it.paths.size} files)\"\n            },\n        )\n\n        // Restore layers one by one, so newer layers can overwrite the old files\n        for ((index, layer) in cacheIndex.layers.withIndex()) {\n            val cache = layer.toCache(index.toString())\n            val restore = cache.restore()\n            if (restore !is RestoreType.Exact) {\n                restoreType = RestoreType.Unknown\n            }\n            debug { \"$name: layer $index, restore=$restore\" }\n        }\n        removeFiles(cacheIndex.deletedFiles)\n        isExactMatch.set(restoreType is RestoreType.Exact)\n        return restoreType\n    }\n\n    override suspend fun save() {\n        if (isExactMatch.get()) {\n            info(\"$name loaded from exact match, no need to update the cache entry\")\n            return\n        }\n\n        val cacheIndex = layers.decode(warnOnMissing = false)\n        val isBaseline = primaryKey.startsWith(baseline)\n        if (cacheIndex == null) {\n            if (!isBaseline) {\n                info(\"$name: old contents is not found, and the current cache $primaryKey does not start with $baseline, so cache saving can't be done\")\n                return\n            }\n            saveSingleLayerCache()\n            return\n        }\n\n        // PR: keep all baseline layers, add one new for PR\n        // branch:\n\n        val caches = cacheIndex.layers\n            .mapIndexed { index, cacheLayer -> cacheLayer.toCache(index.toString()) }\n        val oldContents = caches.associateWith { it.contents() }\n\n        if (isBaseline) {\n            val missing = oldContents.mapNotNull { (cache, contents) ->\n                if (contents == null) cache.primaryKey else null\n            }\n\n            if (missing.isNotEmpty()) {\n                info(\"$name: there are missing layers: $missing\")\n                saveSingleLayerCache()\n                return\n            }\n            if (cacheIndex.layers.size > maxLayers) {\n                info(\"$name: ${cacheIndex.layers.size} layers reached, will create new snapshot\")\n                saveSingleLayerCache()\n                return\n            }\n        }\n\n        // non-baseline\n\n        if (!isBaseline) {\n            val firstLayer = cacheIndex.layers.firstOrNull()\n            val firstBaseline = caches.firstOrNull { it.name.startsWith(baseline) }?.name\n            if (firstLayer?.primaryKey?.startsWith(\"$version-$baseline\") != true) {\n                info(\"$name: the first baseline is not found, and the current cache $primaryKey does not start with $version-$baseline, so cache saving can't be done\")\n                return\n            }\n            if (oldContents.values.firstOrNull() == null) {\n                info(\"$name: the first baseline $firstBaseline was not received, and the current cache $primaryKey does not start with $baseline, so cache saving can't be done\")\n                return\n            }\n        }\n\n        val newContents = hashFilesDetailed(*paths.toTypedArray())\n\n        val oldFiles = mutableMapOf<String, FileDetails>()\n        val reusedFiles = mutableMapOf<String, FileDetails>()\n        val deletedFiles = mutableSetOf<String>()\n        val newLayers = mutableListOf<CacheLayer>()\n        val layerInfo = mutableListOf<String>()\n        for ((layer, contents) in cacheIndex.layers.zip(oldContents.values)) {\n            if (contents == null) {\n                info(\"$name: unknown contents for layer ${layer.primaryKey}\")\n                continue\n            }\n            var helpfulBytes = 0L\n            var wastedBytes = 0L\n            val helpfulLayerFiles = mutableMapOf<String, FileDetails>()\n            val deletedLayerFiles = mutableListOf<String>()\n            for ((file, details) in contents.files) {\n                val newDetails = newContents.contents.files[file]\n                if (details.hash == newDetails?.hash && file !in reusedFiles) {\n                    // same file => previous layer is helpful\n                    helpfulBytes += details.fileSize\n                    helpfulLayerFiles[file] = details\n                } else {\n                    // file is different or removed => previous layer is not useful\n                    if (newDetails == null) {\n                        deletedLayerFiles.add(file)\n                    }\n                    wastedBytes += details.fileSize\n                }\n            }\n            if (wastedBytes >= helpfulBytes) {\n                // Too much waste => remove the layer\n                info(\"$name: layer ${layer.primaryKey} has too much waste (${wastedBytes.formatBytes()} > ${helpfulBytes.formatBytes()}), so the layer will be skipped\")\n                continue\n            }\n            oldFiles += contents.files\n            reusedFiles += helpfulLayerFiles\n            deletedFiles += deletedLayerFiles\n            newLayers += layer\n            layerInfo += \"${layer.primaryKey} ${(helpfulBytes + wastedBytes).formatBytes()} total (${contents.files.size} files), ${wastedBytes.formatBytes()} outdated\"\n        }\n\n        if (!isBaseline && newLayers.isEmpty()) {\n            info(\"$name: at least one layer from the default branch is needed. The new contents is ${newContents.info.totalBytes.formatBytes()} (${newContents.info.totalFiles} files)\")\n            return\n        }\n\n        val diff = diff(HashContents(oldFiles), newContents.contents)\n        if (diff.messages.isNotEmpty()) {\n            info(\"$name: cache contents is changed: ${diff.summary}\")\n        }\n\n        val layer = diff.toLayer()\n        val cache = layer.toCache(\"newlayer\")\n        // TODO: reuse HashDetails when saving cache\n        cache.save()\n\n        newLayers += layer\n        layerInfo += \"${layer.primaryKey} ${diff.totalUpdated.formatBytes()} total (${diff.updatedFiles.size} files), ${diff.totalDeleted.formatBytes()} deleted (${diff.deletedFiles.size} files)\"\n\n        info(layerInfo.joinToString(\"; \", \"$name: ${newLayers.size} layers. \"))\n\n        layers.encode(CacheLayers(newLayers, deletedFiles = deletedFiles.toList()))\n        // Save the index\n        index.save()\n    }\n\n    private suspend fun saveSingleLayerCache() {\n        info(\"$name: creating single-layer cache image\")\n        val layer = CacheLayer(\n            primaryKey = \"$version-$primaryKey\",\n            paths = listOf(),\n        )\n        val cache = layer.toCache(\"single-layer\")\n        cache.save()\n        if (cache.info()?.totalFiles == 0) {\n            // cache is empty => skip creating empty file\n            return\n        }\n        layers.encode(CacheLayers(listOf(layer), deletedFiles = listOf()))\n        index.save()\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/MetadataFile.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport actions.core.warning\nimport com.github.burrunan.wrappers.nodejs.exists\nimport com.github.burrunan.wrappers.nodejs.normalizedPath\nimport kotlinx.serialization.KSerializer\nimport kotlinx.serialization.SerializationException\nimport kotlinx.serialization.json.Json\nimport node.buffer.BufferEncoding\nimport node.fs.*\n\nclass MetadataFile<T>(name: String, private val serializer: KSerializer<T>, private val extension: String = \".json\") {\n    companion object {\n        const val ROOT_FOLDER = \"~/.gradle-cache-action\"\n        val SPECIAL_CHARS = Regex(\"\"\"[!@#$%^&*:;'\"{}\\r\\n\\[\\]\\\\]\"\"\")\n\n        init {\n            val path = ROOT_FOLDER.normalizedPath\n            if (!existsSync(path)) {\n                try {\n                    mkdirSync(path)\n                } catch (ignored: Throwable) {\n                }\n            }\n        }\n    }\n\n    val cachedName = \"$ROOT_FOLDER/$name$extension\"\n    private var uniqueName = cachedName.normalizedPath\n\n    fun prepare(key: String) {\n        uniqueName = \"${cachedName.normalizedPath}.${key.replace('/', '-')}\"\n    }\n\n    suspend fun restore(key: String) {\n        val path = cachedName.normalizedPath\n        if (exists(path)) {\n            prepare(key)\n            rename(path, uniqueName)\n        } else {\n            warning(\"$cachedName: $path does not exist\")\n        }\n    }\n\n    suspend fun decode(warnOnMissing: Boolean = true): T? {\n        if (!exists(uniqueName)) {\n            if (warnOnMissing) {\n                warning(\"$cachedName: $uniqueName does not exist\")\n            }\n            return null\n        }\n        return try {\n            Json.decodeFromString(\n                serializer,\n                readFile(uniqueName, BufferEncoding.utf8)\n            )\n        } catch (e: SerializationException) {\n            warning(\"$cachedName: error deserializing $uniqueName with ${serializer.descriptor.serialName}, message: $e\")\n            return null\n        }\n    }\n\n    suspend fun encode(value: T) {\n        writeFile(\n            cachedName.normalizedPath,\n            Json.encodeToString(serializer, value),\n            BufferEncoding.utf8,\n        )\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/dependenciesCache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.gradle.cache\n\nimport actions.core.ActionsEnvironment\nimport actions.core.debug\nimport com.github.burrunan.gradle.GradleCacheAction\nimport com.github.burrunan.gradle.github.suspendingStateVariable\nimport com.github.burrunan.hashing.hashFiles\nimport octokit.ActionsTrigger\n\n/**\n * Populate cache only when building a default branch, otherwise treat the cache as read-only.\n */\nsuspend fun dependenciesCache(\n    name: String,\n    trigger: ActionsTrigger,\n    cacheLocation: List<String>,\n    pathDependencies: List<String>,\n): Cache {\n    val defaultBranch = GradleCacheAction.DEFAULT_BRANCH_VAR\n    val pkPrefix = trigger.cacheKey\n    val cacheName = \"dependencies-$name\"\n\n    // Avoid re-computing the hash for saving the cache\n    val dependencyDeclarationHash = suspendingStateVariable(cacheName) {\n        hashFiles(*pathDependencies.toTypedArray()).hash\n    }\n    debug { \"$cacheName: dependencyDeclarationHash=${dependencyDeclarationHash.get()}\" }\n    val prefix = \"dependencies-$name-${ActionsEnvironment.RUNNER_OS}\"\n    return LayeredCache(\n        name = cacheName,\n        baseline = prefix,\n        primaryKey = \"$prefix-$pkPrefix-${dependencyDeclarationHash.get()}\",\n        restoreKeys = listOf(\n            \"$prefix-$pkPrefix\",\n            \"$prefix-$defaultBranch\",\n            \"$prefix-master\",\n            \"$prefix-main\",\n        ),\n        paths = cacheLocation,\n    )\n}\n\nsuspend fun gradleDependenciesCache(trigger: ActionsTrigger, path: String, gradleDependenciesCacheKey: List<String>): Cache =\n    dependenciesCache(\n        \"gradle\",\n        trigger,\n        cacheLocation = listOf(\n            \"~/.gradle/caches/modules-2/*\",\n            \"!~/.gradle/caches/modules-2/gc.properties\",\n            \"!~/.gradle/caches/modules-2/modules-2.lock\",\n        ),\n        pathDependencies = listOf(\n            \"$path/**/*.gradle\",\n            \"$path/**/*.gradle.kts\",\n            \"$path/**/gradle/dependency-locking/**\",\n            \"$path/**/*.properties\",\n            \"$path/**/gradle/libs.versions.toml\",\n        ) + gradleDependenciesCacheKey.map {\n                (if (it.startsWith(\"!\")) \"!\" else \"\") +\n                    \"$path/**/\" + it.trim().trimStart('!')\n            } +\n            // Excludes must go the last so they win\n            listOf(\"!$path/**/.gradle/\"),\n    )\n\nsuspend fun mavenDependenciesCache(trigger: ActionsTrigger, path: String, mavenLocalIgnorePaths: List<String>): Cache =\n    dependenciesCache(\n        \"maven\",\n        trigger,\n        cacheLocation = listOf(\"~/.m2/repository\") +\n            mavenLocalIgnorePaths.map { \"!~/.m2/repository/$it\" },\n        pathDependencies = listOf(\n            \"$path/**/pom.xml\",\n        ),\n    )\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/cache/localBuildCache.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.cache\n\nimport com.github.burrunan.gradle.GradleCacheAction\nimport octokit.ActionsTrigger\n\nfun localBuildCache(jobId: String, trigger: ActionsTrigger, gradleVersion: String, treeId: String): Cache {\n    val buildCacheLocation = \"~/.gradle/caches/build-cache-1\"\n    val defaultBranch = GradleCacheAction.DEFAULT_BRANCH_VAR\n    val pkPrefix = trigger.cacheKey\n\n    val restoreKeys = when (trigger) {\n        is ActionsTrigger.PullRequest -> arrayOf(\n            pkPrefix,\n            trigger.event.pull_request.base.ref.removePrefix(\"refs/heads/\"),\n        )\n        is ActionsTrigger.BranchPush -> arrayOf(\n            pkPrefix,\n        )\n        else -> arrayOf()\n    } + arrayOf(\n        defaultBranch,\n        \"master\",\n        \"main\",\n    )\n    val prefix = \"gradle-build-cache-$jobId-gradle-$gradleVersion\"\n    return LayeredCache(\n        name = \"local-build-cache\",\n        baseline = \"$prefix-$defaultBranch\",\n        primaryKey = \"$prefix-$pkPrefix-$treeId\",\n        restoreKeys = restoreKeys.map { \"$prefix-$it\" },\n        paths = listOf(\n            \"$buildCacheLocation/*\",\n            \"!$buildCacheLocation/gc.properties\",\n            \"!$buildCacheLocation/build-cache-1.lock\",\n        ),\n    )\n}\n"
  },
  {
    "path": "layered-cache/src/jsMain/kotlin/com/github/burrunan/gradle/github/StateExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.gradle.github\n\nimport actions.core.getState\nimport actions.core.saveState\n\ninterface MutableStateVariable<T : Any> {\n    fun set(value: T)\n}\n\nopen class BaseStateVariable<T : Any>(protected val name: String) : MutableStateVariable<T> {\n    protected var value: T? = null\n\n    override fun set(value: T) {\n        this.value = value\n        saveState(name, value)\n    }\n}\n\ninterface SuspendingStateVariable<T : Any> : MutableStateVariable<T> {\n    suspend fun get(): T\n}\n\nclass DefaultSuspendingStateVariable(name: String, val default: suspend () -> String) :\n    BaseStateVariable<String>(name), SuspendingStateVariable<String> {\n    override suspend fun get(): String =\n        value ?: getState(name).ifBlank { default() }.also { set(it) }\n}\n\ninterface StateVariable<T : Any> : MutableStateVariable<T> {\n    fun get(): T\n}\n\nclass DefaultStateVariable(name: String, private val default: () -> String) :\n    BaseStateVariable<String>(name), StateVariable<String> {\n    override fun get(): String =\n        value ?: getState(name).ifBlank { default() }.also { set(it) }\n}\n\nfun suspendingStateVariable(name: String, default: suspend () -> String): SuspendingStateVariable<String> =\n    DefaultSuspendingStateVariable(name, default)\n\nfun stateVariable(name: String, default: () -> String = { \"\" }): StateVariable<String> =\n    DefaultStateVariable(name, default)\n\nfun <T : Any, R : Any> StateVariable<T>.transform(decode: (T) -> R, encode: (R) -> T) = object : StateVariable<R> {\n    override fun get(): R = decode(this@transform.get())\n\n    override fun set(value: R) {\n        this@transform.set(encode(value))\n    }\n}\n\nfun StateVariable<String>.toBoolean() = transform({ it == \"Y\" }, { if (it) \"Y\" else \"N\" })\nfun StateVariable<String>.toInt(default: Int) = transform({ if (it.isBlank()) default else it.toInt() }, { it.toString() })\nfun StateVariable<String>.toLong(default: Long) = transform({ if (it.isBlank()) default else it.toLong() }, { it.toString() })\n"
  },
  {
    "path": "layered-cache/src/jsTest/kotlin/com/github/burrunan/gradle/CacheServerTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\npackage com.github.burrunan.gradle\n\nimport actions.cache.RestoreType\nimport actions.cache.restoreAndLog\nimport actions.cache.saveAndLog\nimport com.github.burrunan.gradle.cache.CacheService\nimport com.github.burrunan.gradle.cache.LayeredCache\nimport com.github.burrunan.test.runTest\nimport com.github.burrunan.wrappers.nodejs.mkdir\nimport node.buffer.BufferEncoding\nimport node.fs.readFile\nimport node.fs.unlink\nimport node.fs.writeFile\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass CacheServerTest {\n    val cacheService = CacheService()\n\n    @Test\n    fun saveCache() = runTest {\n        val dir = \"saveCache\"\n        mkdir(dir)\n        val file = \"$dir/cached.txt\"\n        val contents = \"hello, world\"\n        writeFile(file, contents, BufferEncoding.utf8)\n        val patterns = listOf(\"$dir/**\")\n\n        val primaryKey = \"linux-gradle-feature/123123\"\n\n        cacheService {\n            saveAndLog(patterns, primaryKey, \"1-\")\n\n            unlink(file)\n\n            assertEquals(\n                RestoreType.Exact(primaryKey),\n                restoreAndLog(\n                    patterns,\n                    primaryKey,\n                    restoreKeys = listOf(\"linux-gradle-\", \"linux-\"),\n                    version = \"1-\",\n                ),\n                \"Cache restored from exact match\",\n            )\n\n            assertEquals(\n                readFile(file, BufferEncoding.utf8),\n                contents,\n                \"Contents after restore should match\",\n            )\n\n            assertEquals(\n                RestoreType.Partial(primaryKey),\n                restoreAndLog(\n                    patterns,\n                    \"asdf$primaryKey\",\n                    restoreKeys = listOf(\"linux-gradle-\", \"linux-\"),\n                    version = \"1-\",\n                ),\n                \"PK not found => restored from restoreKeys\",\n            )\n\n            assertEquals(\n                readFile(file, BufferEncoding.utf8),\n                contents,\n                \"Contents after restore should match\",\n            )\n        }\n    }\n\n    @Test\n    fun layeredCacheTest() = runTest {\n        val dir = \"saveCache\"\n        mkdir(dir)\n        val file = \"$dir/cached.txt\"\n        val contents = \"hello, world\"\n        writeFile(file, contents, BufferEncoding.utf8)\n        val patterns = listOf(\"$dir/**\")\n\n        val primaryKey = \"prefix-gradle-features/cool/123123\"\n\n        val cache = LayeredCache(\n            \"test-cache\",\n            \"prefix-\",\n            primaryKey = primaryKey,\n            restoreKeys = listOf(\n                \"prefix-gradle-\",\n                \"prefix-\",\n            ),\n            paths = patterns\n        )\n\n        cacheService {\n            assertEquals(\n                RestoreType.None,\n                cache.restore(),\n                \"No data -> RestoreType.None\"\n            )\n\n            cache.save()\n\n            assertEquals(\n                RestoreType.Exact(primaryKey),\n                cache.restore(),\n                \"Restore after saving exact cache -> RestoreType.Exact\"\n            )\n        }\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsTest/kotlin/com/github/burrunan/gradle/GlobTest.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\npackage com.github.burrunan.gradle\n\nimport com.github.burrunan.formatBytes\nimport com.github.burrunan.hashing.hashFilesDetailed\nimport com.github.burrunan.test.runTest\nimport com.github.burrunan.wrappers.nodejs.mkdir\nimport node.buffer.BufferEncoding\nimport node.fs.writeFile\nimport node.path.path\nimport kotlin.test.Test\nimport kotlin.test.assertEquals\n\nclass GlobTest {\n    @Test\n    fun glob() = runTest {\n        val dirName = \"globTest\"\n        val dotGradle = path.join(dirName, \".gradle\")\n        mkdir(dirName)\n        mkdir(dotGradle)\n        writeFile(path.join(dirName, \"settings.gradle\"), \"a\", BufferEncoding.utf8)\n        writeFile(path.join(dirName, \"good.txt\"), \"a\", BufferEncoding.utf8)\n        writeFile(path.join(dirName, \"bad.txt\"), \"a\", BufferEncoding.utf8)\n        writeFile(path.join(dotGradle, \"extra.txt\"), \"a\", BufferEncoding.utf8)\n\n        val hash = hashFilesDetailed(\n            \"$dirName/**/*.gradle\",\n            \"$dirName/**/*.txt\",\n            \"!$dirName/**/.gradle/\",\n            \"!$dirName/**/*bad**\",\n        )\n        val actual = hash.contents.files.entries.joinToString(\"\\n\") { (file, details) ->\n            \"${details.fileSize.formatBytes()} ${details.hash} $file\"\n        }\n        assertEquals(\n            \"\"\"\n            1 B 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 ws:///globTest/good.txt\n            1 B 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 ws:///globTest/settings.gradle\n            \"\"\".trimIndent(),\n            actual,\n        )\n    }\n}\n"
  },
  {
    "path": "layered-cache/src/jsTest/resources/readme.txt",
    "content": ""
  },
  {
    "path": "renovate.json",
    "content": "{\n  \"$schema\": \"https://docs.renovatebot.com/renovate-schema.json\",\n  \"extends\": [\n    \"config:best-practices\"\n  ],\n  \"automerge\": true,\n  \"platformAutomerge\": true,\n  \"labels\": [\"dependencies\"],\n  \"schedule\": [\"every 1 weeks on Monday\"]\n}\n"
  },
  {
    "path": "settings.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npluginManagement {\n    plugins {\n        kotlin(\"multiplatform\") version \"2.3.0\"\n        kotlin(\"plugin.serialization\") version \"2.3.0\"\n    }\n}\n\ndependencyResolutionManagement {\n    repositories {\n        mavenCentral()\n    }\n}\n\nrootProject.name = \"gradle-cache-action\"\n\nenableFeaturePreview(\"TYPESAFE_PROJECT_ACCESSORS\")\n\ninclude(\n    \"cache-service-mock\",\n    \"cache-proxy\",\n    \"gradle-launcher\",\n    \"hashing\",\n    \"layered-cache\",\n    \"cache-action-entrypoint\",\n    \"test-library\",\n    \"wrappers:js\",\n    \"wrappers:nodejs\",\n    \"wrappers:actions-toolkit\",\n    \"wrappers:actions-cache\",\n    \"wrappers:java-properties\",\n    \"wrappers:octokit-request-error\",\n    \"wrappers:octokit-types\",\n    \"wrappers:octokit-webhooks\"\n)\n"
  },
  {
    "path": "test-library/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(kotlin(\"test-js\"))\n                implementation(projects.wrappers.nodejs)\n                implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test-library/src/jsMain/kotlin/com/github/burrunan/test/testExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.test\n\nimport kotlinx.coroutines.GlobalScope\nimport kotlinx.coroutines.promise\nimport node.process.process\n\nfun runTest(block: suspend () -> Unit): dynamic = GlobalScope.promise {\n    process.env[\"RUNNER_OS\"] = \"macos\"\n    block()\n}\n"
  },
  {
    "path": "wrappers/actions-cache/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(\"org.jetbrains.kotlin-wrappers:kotlin-actions-cache\")\n                implementation(projects.wrappers.actionsToolkit)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/actions-cache/src/jsMain/kotlin/actions/cache/CacheExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage actions.cache\n\nimport actions.core.LogLevel\nimport actions.core.info\nimport actions.core.log\nimport actions.core.warning\n\nsuspend fun restoreAndLog(\n    paths: List<String>, primaryKey: String,\n    restoreKeys: List<String> = listOf(),\n    version: String,\n    logLevel: LogLevel = LogLevel.INFO,\n): RestoreType {\n    val result = try {\n        when {\n            restoreKeys.isEmpty() -> restoreCache(paths.toTypedArray(), version + primaryKey)\n            else -> restoreCache(\n                paths.toTypedArray(),\n                version + primaryKey,\n                restoreKeys.map { version + it }.toTypedArray(),\n            )\n        }\n    } catch (t: Throwable) {\n        when (t.asDynamic().name) {\n            \"ValidationError\" -> throw t\n            else -> {\n                warning(\"Error while loading $primaryKey: ${t.message}\")\n                return RestoreType.None\n            }\n        }\n    }\n    result?.removePrefix(version)?.let {\n        return if (it.endsWith(primaryKey)) RestoreType.Exact(it) else RestoreType.Partial(it)\n    }\n    log(logLevel) { \"Cache was not found for version=$version, primaryKey=$primaryKey, restore keys=${restoreKeys.joinToString(\", \")}\" }\n    return RestoreType.None\n}\n\nsuspend fun saveAndLog(\n    paths: List<String>,\n    key: String,\n    version: String,\n    logLevel: LogLevel = LogLevel.INFO,\n) {\n    try {\n        saveCache(paths.toTypedArray(), version + key)\n    } catch (t: Throwable) {\n        // TODO: propagate error\n        when (t.asDynamic().name) {\n            \"ValidationError\" -> throw t\n            \"ReserveCacheError\" -> info(t.message ?: \"Unknown ReserveCacheError\")\n            else -> when {\n                t.message?.contains(\"Cache already exists\") == true ->\n                    log(logLevel) { \"Error while uploading $key: ${t.message}\" }\n                else ->\n                    warning(\"Error while uploading $key: ${t.message}\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/actions-cache/src/jsMain/kotlin/actions/cache/RestoreType.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage actions.cache\n\nsealed class RestoreType {\n    data class Exact(val path: String) : RestoreType()\n    data class Partial(val path: String) : RestoreType()\n    object None : RestoreType() {\n        override fun toString() = \"None\"\n    }\n    object Unknown : RestoreType() {\n        override fun toString() = \"Unknown\"\n    }\n}\n"
  },
  {
    "path": "wrappers/actions-cache/src/jsMain/kotlin/actions/cache/internal/CacheContract.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n@file:JsModule(\"@actions/cache/lib/internal/constants\")\npackage actions.cache.internal\n\nimport actions.cache.HttpClientError\n\nexternal interface GetCacheParams {\n    val keys: String\n    val version: String\n}\n\nexternal interface ReserveCacheRequest {\n    val key: String\n    val version: String?\n    var cacheSize: Number?\n}\n\nexternal interface ReserveCacheResponse {\n    var cacheId: Number\n}\n\nexternal interface ArtifactCacheEntry {\n    var cacheKey: String?\n    var scope: String?\n    var creationTime: String?\n    var archiveLocation: String?\n}\n\nexternal interface CommitCacheRequest {\n    val size: Number\n}\n\nexternal interface InternalCacheOptions {\n    var compressionMethod: CompressionMethod?\n    var cacheSize: Number?\n}\n\nexternal enum class CompressionMethod {\n    Gzip,\n\n    // Long range mode was added to zstd in v1.3.2.\n    // This enum is for earlier version of zstd that does not have --long support\n    ZstdWithoutLong,\n    Zstd\n}\n\nexternal interface ITypedResponse<T> {\n    var statusCode: Number\n    var result: T?\n    var headers: Any\n}\n\nexternal interface ITypedResponseWithError<T>: ITypedResponse<T> {\n    val error: HttpClientError?\n}\n"
  },
  {
    "path": "wrappers/actions-cache/src/jsMain/kotlin/actions/cache/internal/httpclient.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@file:JsModule(\"@actions/cache/lib/internal/cacheHttpClient\")\n@file:JsNonModule\npackage actions.cache.internal\n\nimport actions.cache.DownloadOptions\nimport actions.cache.UploadOptions\nimport actions.cache.internal.ArtifactCacheEntry\nimport actions.cache.internal.InternalCacheOptions\nimport kotlin.js.Promise\n\nexternal fun getCacheEntry(\n    keys: Array<String>,\n    paths: Array<String>,\n    options: InternalCacheOptions = definedExternally\n): Promise<ArtifactCacheEntry?>\n\nexternal fun reserveCache(\n    key: String,\n    paths: Array<String>,\n    options: InternalCacheOptions = definedExternally\n): Promise<ITypedResponseWithError<ReserveCacheResponse>>\n\nexternal fun saveCache(\n    cacheId: Number,\n    archivePath: String,\n    options: UploadOptions? = definedExternally,\n): Promise<Unit>\n\nexternal fun downloadCache(\n    archiveLocation: String,\n    archivePath: String,\n    options: DownloadOptions? = definedExternally,\n): Promise<Unit>\n"
  },
  {
    "path": "wrappers/actions-cache/src/jsMain/kotlin/actions/cache/types.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage actions.cache\n\ntypealias ValidationError = Error\n\ntypealias ReserveCacheError = Error\n\ntypealias HttpClientError = Error\n"
  },
  {
    "path": "wrappers/actions-toolkit/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(projects.wrappers.nodejs)\n                api(\"org.jetbrains.kotlin-wrappers:kotlin-actions-core\")\n                api(\"org.jetbrains.kotlin-wrappers:kotlin-actions-exec\")\n                api(\"org.jetbrains.kotlin-wrappers:kotlin-actions-glob\")\n                implementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-core\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/ActionFailedException.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage actions.core\n\nclass ActionFailedException(override val message: String, cause: Throwable? = null) :\n    Throwable(message, cause)\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/ActionStage.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage actions.core\n\nenum class ActionStage {\n    PRE, MAIN, POST\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/ActionsEnvironment.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage actions.core\n\nimport node.process.process\nimport kotlin.reflect.KProperty\n\n/**\n * See https://docs.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables\n */\nobject ActionsEnvironment {\n    val HOME by Environment\n    val GITHUB_WORKFLOW by Environment\n    val GITHUB_RUN_ID by Environment\n    val GITHUB_RUN_NUMBER by Environment\n    val GITHUB_ACTION by Environment\n    val GITHUB_ACTOR by Environment\n    val GITHUB_REPOSITORY by Environment\n    val GITHUB_EVENT_NAME by Environment\n    val GITHUB_EVENT_PATH by Environment\n    val GITHUB_WORKSPACE by Environment\n    val GITHUB_SHA by Environment\n    val GITHUB_REF by Environment\n    val GITHUB_HEAD_REF by Environment\n    val GITHUB_BASE_REF by Environment\n    val GITHUB_SERVER_URL by Environment\n    val GITHUB_API_URL by Environment\n    val GITHUB_GRAPHQL_URL by Environment\n    val RUNNER_OS by Environment\n}\n\nprivate object Environment {\n    operator fun getValue(environment: Any, property: KProperty<*>): String =\n        process.env[property.name] ?: throw ActionFailedException(\"${property.name} is not found in process.env\")\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/LogLevel.kt",
    "content": "package actions.core\n\nenum class LogLevel {\n    DEBUG,\n    INFO,\n    NONE,\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/LoggingExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage actions.core\n\ninline fun debug(message: () -> String) {\n    if (isDebug()) {\n        debug(message())\n    }\n}\n\ninline fun log(logLevel: LogLevel, message: () -> String) {\n    when(logLevel) {\n        LogLevel.DEBUG -> debug(message)\n        LogLevel.INFO -> info(message())\n        LogLevel.NONE -> Unit\n    }\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/ext/Group.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage actions.core.ext\n\nimport actions.core.endGroup\nimport actions.core.startGroup\n\ninline fun<T> group(name: String, action: () -> T): T {\n    startGroup(name)\n    try {\n        return action()\n    } finally {\n        endGroup()\n    }\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/core/ext/InputExtensions.kt",
    "content": "package actions.core.ext\n\nimport actions.core.InputOptions\n\nfun getInput(name: String, required: Boolean = false): String =\n    actions.core.getInput(name, InputOptions(required = required))\n\nprivate val LINE_SEPARATOR = Regex(\"[\\r\\n]+\")\n\nfun getListInput(name: String, required: Boolean = false): List<String> =\n    actions.core.getInput(name, InputOptions(required = required))\n        .split(LINE_SEPARATOR)\n        .map { it.trim() }\n        .filterNot { it.isEmpty() }\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/exec/ExecExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage actions.exec\n\nclass ExecResult(\n    val exitCode: Int,\n    val stdout: String,\n    val stderr: String,\n)\n\nsuspend fun exec(\n    commandLine: String, vararg args: String,\n    captureOutput: Boolean = false,\n    options: (ExecOptions) -> ExecOptions = { it }\n): ExecResult {\n    val stdout = mutableListOf<String>()\n    val stderr = mutableListOf<String>()\n    val execOptions = if (!captureOutput) {\n        ExecOptions()\n    } else {\n        ExecOptions(\n            listeners = ExecListeners(\n                stdout = {\n                    // it.toString() results in [...] for unknown reason\n                    stdout.add(\"\" + it.unsafeCast<String>())\n                },\n                stderr = {\n                    // it.toString() results in [...] for unknown reason\n                    stderr.add(\"\" + it.unsafeCast<String>())\n                }\n            )\n        )\n    }\n    val exitCode = exec(\n        commandLine,\n        args.copyOf(),\n        options(execOptions),\n    )\n    return ExecResult(\n        exitCode = exitCode.toInt(),\n        stdout = stdout.joinToString(\"\\n\"),\n        stderr = stderr.joinToString(\"\\n\")\n    )\n}\n"
  },
  {
    "path": "wrappers/actions-toolkit/src/jsMain/kotlin/actions/glob/removeFiles.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage actions.glob\n\nimport js.promise.await\nimport kotlinx.coroutines.launch\nimport kotlinx.coroutines.supervisorScope\nimport node.fs.unlink\n\nsuspend fun removeFiles(files: List<String>) {\n    if (files.isEmpty()) {\n        return\n    }\n    val globber = create(files.joinToString(\"\\n\"))\n    val fileNames = globber.glob().await()\n    supervisorScope {\n        for (file in fileNames) {\n            launch {\n                unlink(file)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/java-properties/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(npm(\"java-properties\", \"1.0.2\"))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/java-properties/src/jsMain/kotlin/javaproperties/index.module_java-properties.kt",
    "content": "@file:JsModule(\"java-properties\")\n@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage javaproperties\n\nimport kotlin.js.Json\n\nopen external class PropertiesFile(vararg args: String) {\n    open var objs: Json\n    open fun makeKeys(line: String)\n    open fun addFile(file: String)\n    open fun of(vararg args: String)\n    open fun get(key: String, defaultValue: String = definedExternally): dynamic /* String? | Array<String>? */\n    open fun getLast(key: String, defaultValue: String = definedExternally): String?\n    open fun getFirst(key: String, defaultValue: String = definedExternally): String?\n    open fun getInt(key: String, defaultIntValue: Number = definedExternally): Number?\n    open fun getFloat(key: String, defaultFloatValue: Number = definedExternally): Number?\n    open fun getBoolean(key: String, defaultBooleanValue: Boolean = definedExternally): Boolean\n    open fun set(key: String, value: String)\n    open fun interpolate(s: String): String\n    open fun getKeys(): Array<String>\n    open fun getMatchingKeys(matchstr: String): Array<String>\n    open fun reset()\n}\n\nexternal fun of(args: Any): PropertiesFile\n"
  },
  {
    "path": "wrappers/java-properties/src/jsMain/kotlin/javaproperties/parseString.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage javaproperties\n\nprivate val NEWLINE = Regex(\"\\\\s*[\\r\\n]+\\\\s*\")\n\nfun parseString(text: String) = PropertiesFile().apply {\n    for(line in text.split(NEWLINE)) {\n        makeKeys(line)\n    }\n}\n"
  },
  {
    "path": "wrappers/js/src/jsMain/kotlin/com/github/burrunan/formatBytes.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan\n\nfun Long.formatBytes() = when {\n    this < 5 * 1024 -> \"${this} B\"\n    this < 5 * 1024 * 1204 -> \"${(this + 512L) / (1024L)} KiB\"\n    this < 5L * 1024 * 1204 * 1024 -> \"${(this + 512L * 1024) / (1024L * 1024)} MiB\"\n    else -> \"${(this + 512L * 1024 * 1024) / (1024L * 1024 * 1024)} GiB\"\n}\n"
  },
  {
    "path": "wrappers/js/src/jsMain/kotlin/com/github/burrunan/wrappers/js/SuspendExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.wrappers.js\n\nimport kotlin.coroutines.resume\nimport kotlin.coroutines.resumeWithException\nimport kotlin.coroutines.suspendCoroutine\n\nsuspend inline fun suspendWithCallback(crossinline block: ((Throwable?) -> Unit) -> Unit) =\n    suspendCoroutine<Nothing?> { cont ->\n        block.invoke { error ->\n            when (error) {\n                null -> cont.resume(null)\n                else -> cont.resumeWithException(error)\n            }\n        }\n    }\n\nsuspend inline fun <T : Any> suspendWithCallback(crossinline block: ((Throwable?, result: T) -> Unit) -> Unit) =\n    suspendCoroutine<T> { cont ->\n        block.invoke { error, result ->\n            when (error) {\n                null -> cont.resume(result)\n                else -> cont.resumeWithException(error)\n            }\n        }\n    }\n"
  },
  {
    "path": "wrappers/nodejs/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(projects.wrappers.js)\n                api(\"org.jetbrains.kotlin-wrappers:kotlin-node\")\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/nodejs/src/jsMain/kotlin/com/github/burrunan/wrappers/nodejs/FsExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.github.burrunan.wrappers.nodejs\n\nimport js.objects.unsafeJso\nimport node.fs.MakeDirectoryOptions\nimport node.fs.existsSync\nimport node.fs.mkdir\n\nsuspend fun mkdir(path: String) {\n    if (!exists(path)) {\n        mkdir(path, unsafeJso<MakeDirectoryOptions> { recursive = true })\n    }\n}\n\n@Deprecated(message = \"catch errors instead\", level = DeprecationLevel.WARNING)\nfun exists(path: String) =\n    existsSync(path.normalizedPath)\n\nval String.normalizedPath: String\n    get() = when {\n        startsWith(\"~\") -> node.os.homedir() + substring(1)\n        else -> this\n    }\n"
  },
  {
    "path": "wrappers/nodejs/src/jsMain/kotlin/com/github/burrunan/wrappers/nodejs/StreamExtensions.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.github.burrunan.wrappers.nodejs\n\nimport js.objects.unsafeJso\nimport node.ReadableStream\nimport node.WritableStream\nimport node.buffer.Buffer\nimport node.stream.Readable\nimport node.stream.consumers.buffer\nimport node.stream.consumers.json\nimport node.stream.finished\n\nsuspend fun <T> Readable.readJson(): T = json(this) as T\n\nsuspend fun Readable.readToBuffer(): Buffer<*> = buffer(this)\n\nsuspend fun <T : ReadableStream, D: WritableStream> T.pipeAndWait(destination: D, end : Boolean = false) {\n    pipe(destination = destination, options = unsafeJso { this.end = end })\n    finished(this)\n}\n"
  },
  {
    "path": "wrappers/octokit-request-error/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(projects.wrappers.octokitTypes)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/octokit-request-error/src/jsMain/kotlin/octokit/requesterror/index.module_@octokit_request-error.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\n\npackage octokit.requesterror\n\ntypealias RequestError = Error\n"
  },
  {
    "path": "wrappers/octokit-request-error/src/jsMain/kotlin/octokit/requesterror/types.module_@octokit_request-error.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\n\npackage octokit.requesterror\n\nimport octokit.types.RequestOptions\nimport octokit.types.ResponseHeaders\n\nexternal interface RequestErrorOptions {\n    var headers: ResponseHeaders?\n    var request: RequestOptions\n}\n"
  },
  {
    "path": "wrappers/octokit-types/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(projects.wrappers.nodejs)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/AuthInterface.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nimport kotlin.js.Promise\n\nexternal interface AuthInterfaceHook {\n    @nativeInvoke\n    operator fun <T> invoke(request: RequestInterface__0, options: RequestParameters /* RequestParameters & `T$6` */): Promise<OctokitResponse<T>>\n    @nativeInvoke\n    operator fun <T> invoke(request: RequestInterface__0, route: Route, parameters: RequestParameters = definedExternally): Promise<OctokitResponse<T>>\n}\n\nexternal interface AuthInterface<AuthOptions : Array<Any>, Authentication : Any?> {\n    @nativeInvoke\n    operator fun invoke(vararg args: AuthOptions): Promise<Authentication>\n    var hook: AuthInterfaceHook\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/EndpointDefaults.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\nexternal interface EndpointDefaultsRequestHeader: RequestHeaders {\n}\n\nexternal interface EndpointDefaultsMediaType {\n    var format: String\n    var previews: Array<String>\n}\n\nexternal interface EndpointDefaults {\n    var baseUrl: Url\n    var method: String /* \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\" */\n    var url: Url?\n    var headers: EndpointDefaultsRequestHeader\n    var mediaType: EndpointDefaultsMediaType\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/EndpointInterface.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nexternal interface `T$4` {\n    var method: String?\n}\n\nexternal interface MergeFunction<D> {\n    @nativeInvoke\n    operator fun <P : RequestParameters> invoke(route: Any, parameters: P = definedExternally): D /* D & Any & P */\n    @nativeInvoke\n    operator fun <@Suppress(\"FINAL_UPPER_BOUND\") R : Route, P : RequestParameters> invoke(route: R, parameters: P = definedExternally): D /* D & Any & P */\n    @nativeInvoke\n    operator fun <P : RequestParameters> invoke(options: P): RequestParameters /* RequestParameters & `T$3` */\n    @nativeInvoke\n    operator fun invoke(): D /* D & RequestParameters */\n}\n\nexternal interface EndpointInterface<D : Any?> {\n    @nativeInvoke\n    operator fun <O : RequestParameters> invoke(options: O /* O & `T$4` & Any */): RequestOptions /* RequestOptions & Pick<D /* D & O */, Any> */\n    @nativeInvoke\n    operator fun <P : RequestParameters> invoke(route: Any, parameters: P = definedExternally): Any /* Any & Any */\n    @nativeInvoke\n    operator fun <@Suppress(\"FINAL_UPPER_BOUND\") R : Route, P : RequestParameters> invoke(route: R, parameters: P = definedExternally): Any /* Any & Any */\n    var DEFAULTS: D /* D & RequestParameters */\n//    var defaults: (newDefaults: O) -> EndpointInterface<D /* D & O */>\n    var defaults: EndpointInterfaceDefaults<D>\n    var merge: MergeFunction<Any?>\n    var parse: EndpointInterfaceOptionParser\n}\n\nexternal interface EndpointInterfaceDefaults<D> {\n    @nativeInvoke\n    operator fun<O: RequestParameters> invoke(newDefaults: O): EndpointInterface<D /* D & O */>\n}\n\nexternal interface EndpointInterfaceOptionParser {\n    @nativeInvoke\n    operator fun<O: RequestOptions> invoke(options: O): RequestOptions /*& Pick<O, keyof RequestOptions>*/\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/EndpointOptions.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\nexternal interface `T$6` {\n    var method: String /* \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\" */\n    var url: Url\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/Fetch.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\ntypealias Fetch = Any\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/GetResponseTypeFromEndpointMethod.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\ntypealias Unwrap<@Suppress(\"UNUSED_TYPEALIAS_PARAMETER\") T> = Any\n\ntypealias AnyFunction = (args: Any) -> Any\n\ntypealias GetResponseTypeFromEndpointMethod<@Suppress(\"UNUSED_TYPEALIAS_PARAMETER\") T> = Unwrap<dynamic /*ReturnType<T>*/>\n\ntypealias GetResponseDataTypeFromEndpointMethod<@Suppress(\"UNUSED_TYPEALIAS_PARAMETER\") T> = Any\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/OctokitResponse.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\nexternal interface OctokitResponse<T> {\n    var headers: ResponseHeaders\n    var status: Number\n    var url: Url\n    var data: T\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/RequestError.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\nexternal interface `T$7` {\n    var resource: String\n    var code: String\n    var field: String\n    var message: String?\n}\n\nexternal interface RequestError {\n    var name: String\n    var status: Number\n    var documentation_url: String\n    var errors: Array<`T$7`>?\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/RequestHeaders.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nexternal interface RequestHeaders {\n    var accept: String?\n    var authorization: String?\n    @nativeGetter\n    operator fun get(header: String): Any? /* String? | Number? */\n    @nativeSetter\n    operator fun set(header: String, value: String?)\n    @nativeSetter\n    operator fun set(header: String, value: Number?)\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/RequestInterface.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nimport kotlin.js.Promise\n\nexternal interface RequestInterface<D : Any?> {\n    @nativeInvoke\n    operator fun <T, O : RequestParameters> invoke(options: O /* O & `T$4` & Any */): Promise<OctokitResponse<T>>\n    @nativeInvoke\n    operator fun invoke(route: Any, options: Any = definedExternally): Any\n    @nativeInvoke\n    operator fun <@Suppress(\"FINAL_UPPER_BOUND\") R : Route> invoke(route: R, options: Any = definedExternally): Any\n//    var defaults: (newDefaults: O) -> RequestInterface<D /* D & O */>\n    var defaults: RequestInterfaceDefaults<D>\n    var endpoint: EndpointInterface<D>\n}\n\nexternal interface RequestInterface__0 : RequestInterface<Any?>\n\nexternal interface RequestInterfaceDefaults<D> {\n    @nativeInvoke\n    operator fun<O: RequestParameters> invoke(newDefaults: O): RequestInterface<D /* D & O */>\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/RequestOptions.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\nexternal interface RequestOptions {\n    var method: String /* \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\" */\n    var url: Url\n    var headers: RequestHeaders\n    var body: Any?\n    var request: RequestRequestOptions?\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/RequestParameters.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nexternal interface `T$8` {\n    var format: String?\n    var previews: Array<String>?\n}\n\nexternal interface RequestParameters {\n    var baseUrl: Url?\n    var headers: RequestHeaders?\n    var mediaType: `T$8`?\n    var request: RequestRequestOptions?\n    @nativeGetter\n    operator fun get(parameter: String): Any?\n    @nativeSetter\n    operator fun set(parameter: String, value: Any)\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/RequestRequestOptions.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nexternal interface RequestRequestOptions {\n    var agent: Any?\n    var fetch: Fetch?\n    var signal: Signal?\n    var timeout: Number?\n    @nativeGetter\n    operator fun get(option: String): Any?\n    @nativeSetter\n    operator fun set(option: String, value: Any)\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/ResponseHeaders.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nexternal interface ResponseHeaders {\n    var date: String?\n    var etag: String?\n    var link: String?\n    var location: String?\n    var server: String?\n    var status: String?\n    var vary: String?\n    @nativeGetter\n    operator fun get(header: String): Any? /* String? | Number? */\n    @nativeSetter\n    operator fun set(header: String, value: String?)\n    @nativeSetter\n    operator fun set(header: String, value: Number?)\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/Route.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\ntypealias Route = String\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/Signal.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\ntypealias Signal = Any\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/StrategyInterface.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\npackage octokit.types\n\nexternal interface StrategyInterface<StrategyOptions : Array<Any>, AuthOptions : Array<Any>, Authentication : Any?> {\n    @nativeInvoke\n    operator fun invoke(vararg args: StrategyOptions): AuthInterface<AuthOptions, Authentication>\n}\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/Url.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\ntypealias Url = String\n"
  },
  {
    "path": "wrappers/octokit-types/src/jsMain/kotlin/octokit/types/VERSION.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.types\n\nexternal var VERSION: Any\n"
  },
  {
    "path": "wrappers/octokit-webhooks/build.gradle.kts",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nkotlin {\n    sourceSets {\n        jsMain {\n            dependencies {\n                api(projects.wrappers.octokitRequestError)\n                api(npm(\"@octokit/webhooks\", \"13.8.2\"))\n                implementation(projects.wrappers.actionsToolkit)\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "wrappers/octokit-webhooks/src/jsMain/kotlin/octokit/ActionsTrigger.kt",
    "content": "/*\n * Copyright 2020 Vladimir Sitnikov <sitnikov.vladimir@gmail.com>\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage octokit\n\nimport actions.core.ActionsEnvironment\nimport node.buffer.BufferEncoding\nimport node.fs.readFile\nimport octokit.webhooks.WebhookPayloadPullRequest\nimport octokit.webhooks.WebhookPayloadPush\nimport octokit.webhooks.WebhookPayloadWorkflowDispatch\n\nsealed class ActionsTrigger(val name: String, open val event: Any) {\n    class PullRequest(override val event: WebhookPayloadPullRequest) : ActionsTrigger(\"pull_request\", event)\n    class BranchPush(override val event: WebhookPayloadPush) : ActionsTrigger(\"push\", event)\n    class WorkflowDispatch(override val event: WebhookPayloadWorkflowDispatch) : ActionsTrigger(\"workflow_dispatch\", event)\n    class Schedule(name: String, event: Any) : ActionsTrigger(name, event)\n    class Other(name: String, event: Any) : ActionsTrigger(name, event)\n}\n\nsuspend fun currentTrigger(): ActionsTrigger {\n    val eventString = readFile(ActionsEnvironment.GITHUB_EVENT_PATH, BufferEncoding.utf8)\n    val event = JSON.parse<Any>(eventString)\n    @Suppress(\"UNCHECKED_CAST_TO_EXTERNAL_INTERFACE\")\n    return when (val eventName = ActionsEnvironment.GITHUB_EVENT_NAME) {\n        \"pull_request\" -> ActionsTrigger.PullRequest(event as WebhookPayloadPullRequest)\n        \"push\" -> ActionsTrigger.BranchPush(event as WebhookPayloadPush)\n        \"workflow_dispatch\" -> ActionsTrigger.WorkflowDispatch(event as WebhookPayloadWorkflowDispatch)\n        \"schedule\" -> ActionsTrigger.Schedule(eventName, event)\n        else -> ActionsTrigger.Other(eventName, event)\n    }\n}\n"
  },
  {
    "path": "wrappers/octokit-webhooks/src/jsMain/kotlin/octokit/webhooks/ResponseHeaders.module_@octokit_types.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"DEPRECATION\")\n\nexternal interface ResponseHeaders {\n    var date: String?\n    var etag: String?\n    var link: String?\n    var location: String?\n    var server: String?\n    var status: String?\n    var vary: String?\n    @nativeGetter\n    operator fun get(header: String): Any? /* String? | Number? */\n    @nativeSetter\n    operator fun set(header: String, value: String?)\n    @nativeSetter\n    operator fun set(header: String, value: Number?)\n}\n"
  },
  {
    "path": "wrappers/octokit-webhooks/src/jsMain/kotlin/octokit/webhooks/event-payloads.EventPayloads.module_@octokit_webhooks.kt",
    "content": "@file:JsModule(\"@octokit/webhooks\")\n@file:JsQualifier(\"EventPayloads\")\n@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\npackage octokit.webhooks\n\nexternal interface WebhookPayloadWorkflowRunSender {\n    var avatar_url: String\n    var events_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var gravatar_id: String\n    var html_url: String\n    var id: Number\n    var login: String\n    var node_id: String\n    var organizations_url: String\n    var received_events_url: String\n    var repos_url: String\n    var site_admin: Boolean\n    var starred_url: String\n    var subscriptions_url: String\n    var type: String\n    var url: String\n}\n\nexternal interface WebhookPayloadWorkflowRunOrganization {\n    var avatar_url: String\n    var description: String\n    var events_url: String\n    var hooks_url: String\n    var id: Number\n    var issues_url: String\n    var login: String\n    var members_url: String\n    var node_id: String\n    var public_members_url: String\n    var repos_url: String\n    var url: String\n}\n\nexternal interface WebhookPayloadWorkflowRun {\n    var action: String\n    var organization: WebhookPayloadWorkflowRunOrganization\n    var repository: PayloadRepository\n    var sender: WebhookPayloadWorkflowRunSender\n}\n\nexternal interface WebhookPayloadWorkflowDispatchSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadWorkflowDispatchOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadWorkflowDispatchInputs\n\nexternal interface WebhookPayloadWorkflowDispatch {\n    var inputs: WebhookPayloadWorkflowDispatchInputs\n    var ref: String\n    var repository: PayloadRepository\n    var organization: WebhookPayloadWorkflowDispatchOrganization\n    var sender: WebhookPayloadWorkflowDispatchSender\n    var workflow: String\n}\n\nexternal interface WebhookPayloadWatchSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadWatch {\n    var action: String\n    var repository: PayloadRepository\n    var sender: WebhookPayloadWatchSender\n}\n\nexternal interface WebhookPayloadTeamAddSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadTeamAddOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadTeamAddTeam {\n    var name: String\n    var id: Number\n    var node_id: String\n    var slug: String\n    var description: String\n    var privacy: String\n    var url: String\n    var html_url: String\n    var members_url: String\n    var repositories_url: String\n    var permission: String\n}\n\nexternal interface WebhookPayloadTeamAdd {\n    var team: WebhookPayloadTeamAddTeam\n    var repository: PayloadRepository\n    var organization: WebhookPayloadTeamAddOrganization\n    var sender: WebhookPayloadTeamAddSender\n}\n\nexternal interface WebhookPayloadTeamChanges\n\nexternal interface WebhookPayloadTeamSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadTeamOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface PayloadRepositoryPermissions {\n    var pull: Boolean\n    var push: Boolean\n    var admin: Boolean\n}\n\nexternal interface WebhookPayloadTeamTeam {\n    var name: String\n    var id: Number\n    var node_id: String\n    var slug: String\n    var description: String?\n    var privacy: String\n    var url: String\n    var html_url: String\n    var members_url: String\n    var repositories_url: String\n    var permission: String\n}\n\nexternal interface WebhookPayloadTeam {\n    var action: String\n    var team: WebhookPayloadTeamTeam\n    var repository: PayloadRepository?\n    var organization: WebhookPayloadTeamOrganization\n    var sender: WebhookPayloadTeamSender\n    var changes: WebhookPayloadTeamChanges?\n}\n\nexternal interface WebhookPayloadStatusSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadStatusBranchesItemCommit {\n    var sha: String\n    var url: String\n}\n\nexternal interface WebhookPayloadStatusBranchesItem {\n    var name: String\n    var commit: WebhookPayloadStatusBranchesItemCommit\n    var protected: Boolean\n}\n\nexternal interface WebhookPayloadStatusCommitCommitter {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadStatusCommitAuthor {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadStatusCommitCommitVerification {\n    var verified: Boolean\n    var reason: String\n    var signature: String\n    var payload: String\n}\n\nexternal interface WebhookPayloadStatusCommitCommitTree {\n    var sha: String\n    var url: String\n}\n\nexternal interface WebhookPayloadStatusCommitCommitCommitter {\n    var name: String\n    var email: String\n    var date: String\n}\n\nexternal interface WebhookPayloadStatusCommitCommitAuthor {\n    var name: String\n    var email: String\n    var date: String\n}\n\nexternal interface WebhookPayloadStatusCommitCommit {\n    var author: WebhookPayloadStatusCommitCommitAuthor\n    var committer: WebhookPayloadStatusCommitCommitCommitter\n    var message: String\n    var tree: WebhookPayloadStatusCommitCommitTree\n    var url: String\n    var comment_count: Number\n    var verification: WebhookPayloadStatusCommitCommitVerification\n}\n\nexternal interface WebhookPayloadStatusCommit {\n    var sha: String\n    var node_id: String\n    var commit: WebhookPayloadStatusCommitCommit\n    var url: String\n    var html_url: String\n    var comments_url: String\n    var author: WebhookPayloadStatusCommitAuthor\n    var committer: WebhookPayloadStatusCommitCommitter\n    var parents: Array<Any>\n}\n\nexternal interface WebhookPayloadStatus {\n    var id: Number\n    var sha: String\n    var name: String\n    var target_url: Any?\n    var context: String\n    var description: Any?\n    var state: String\n    var commit: WebhookPayloadStatusCommit\n    var branches: Array<WebhookPayloadStatusBranchesItem>\n    var created_at: String\n    var updated_at: String\n    var repository: PayloadRepository\n    var sender: WebhookPayloadStatusSender\n}\n\nexternal interface WebhookPayloadStarSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadStar {\n    var action: String\n    var starred_at: String?\n    var repository: PayloadRepository\n    var sender: WebhookPayloadStarSender\n}\n\nexternal interface WebhookPayloadSponsorshipChangesTierFrom {\n    var node_id: String\n    var created_at: String\n    var description: String\n    var monthly_price_in_cents: Number\n    var monthly_price_in_dollars: Number\n    var name: String\n}\n\nexternal interface WebhookPayloadSponsorshipChangesTier {\n    var from: WebhookPayloadSponsorshipChangesTierFrom\n}\n\nexternal interface WebhookPayloadSponsorshipChanges {\n    var tier: WebhookPayloadSponsorshipChangesTier\n}\n\nexternal interface WebhookPayloadSponsorshipSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadSponsorshipSponsorshipTier {\n    var node_id: String\n    var created_at: String\n    var description: String\n    var monthly_price_in_cents: Number\n    var monthly_price_in_dollars: Number\n    var name: String\n}\n\nexternal interface WebhookPayloadSponsorshipSponsorshipSponsor {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadSponsorshipSponsorshipSponsorable {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadSponsorshipSponsorship {\n    var node_id: String\n    var created_at: String\n    var sponsorable: WebhookPayloadSponsorshipSponsorshipSponsorable\n    var sponsor: WebhookPayloadSponsorshipSponsorshipSponsor\n    var privacy_level: String\n    var tier: WebhookPayloadSponsorshipSponsorshipTier\n}\n\nexternal interface WebhookPayloadSponsorship {\n    var action: String\n    var sponsorship: WebhookPayloadSponsorshipSponsorship\n    var sender: WebhookPayloadSponsorshipSender\n    var changes: WebhookPayloadSponsorshipChanges?\n    var effective_date: String?\n}\n\nexternal interface WebhookPayloadSecurityAdvisorySecurityAdvisoryVulnerabilitiesItemFirstPatchedVersion {\n    var identifier: String\n}\n\nexternal interface WebhookPayloadSecurityAdvisorySecurityAdvisoryVulnerabilitiesItemPackage {\n    var ecosystem: String\n    var name: String\n}\n\nexternal interface WebhookPayloadSecurityAdvisorySecurityAdvisoryVulnerabilitiesItem {\n    var `package`: WebhookPayloadSecurityAdvisorySecurityAdvisoryVulnerabilitiesItemPackage\n    var severity: String\n    var vulnerable_version_range: String\n    var first_patched_version: WebhookPayloadSecurityAdvisorySecurityAdvisoryVulnerabilitiesItemFirstPatchedVersion\n}\n\nexternal interface WebhookPayloadSecurityAdvisorySecurityAdvisoryReferencesItem {\n    var url: String\n}\n\nexternal interface WebhookPayloadSecurityAdvisorySecurityAdvisoryIdentifiersItem {\n    var value: String\n    var type: String\n}\n\nexternal interface WebhookPayloadSecurityAdvisorySecurityAdvisory {\n    var ghsa_id: String\n    var summary: String\n    var description: String\n    var severity: String\n    var identifiers: Array<WebhookPayloadSecurityAdvisorySecurityAdvisoryIdentifiersItem>\n    var references: Array<WebhookPayloadSecurityAdvisorySecurityAdvisoryReferencesItem>\n    var published_at: String\n    var updated_at: String\n    var withdrawn_at: Any?\n    var vulnerabilities: Array<WebhookPayloadSecurityAdvisorySecurityAdvisoryVulnerabilitiesItem>\n}\n\nexternal interface WebhookPayloadSecurityAdvisory {\n    var action: String\n    var security_advisory: WebhookPayloadSecurityAdvisorySecurityAdvisory\n}\n\nexternal interface WebhookPayloadRepositoryVulnerabilityAlertAlertDismisser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadRepositoryVulnerabilityAlertSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadRepositoryVulnerabilityAlertAlert {\n    var id: Number\n    var affected_range: String\n    var affected_package_name: String\n    var external_reference: String\n    var external_identifier: String\n    var fixed_in: String\n    var dismisser: WebhookPayloadRepositoryVulnerabilityAlertAlertDismisser?\n    var dismiss_reason: String?\n    var dismissed_at: String?\n}\n\nexternal interface WebhookPayloadRepositoryVulnerabilityAlert {\n    var action: String\n    var alert: WebhookPayloadRepositoryVulnerabilityAlertAlert\n    var repository: PayloadRepository?\n    var sender: WebhookPayloadRepositoryVulnerabilityAlertSender?\n}\n\nexternal interface WebhookPayloadRepositoryImportSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadRepositoryImportOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadRepositoryImport {\n    var status: String\n    var repository: PayloadRepository\n    var organization: WebhookPayloadRepositoryImportOrganization\n    var sender: WebhookPayloadRepositoryImportSender\n}\n\nexternal interface WebhookPayloadRepositoryOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadRepositorySender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadRepository {\n    var action: String\n    var repository: PayloadRepository\n    var sender: WebhookPayloadRepositorySender\n    var organization: WebhookPayloadRepositoryOrganization?\n}\n\nexternal interface WebhookPayloadRepositoryDispatchInstallation {\n    var id: Number\n    var node_id: String\n}\n\nexternal interface WebhookPayloadRepositoryDispatchSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadRepositoryDispatchOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadRepositoryDispatchClientPayload\n\nexternal interface WebhookPayloadRepositoryDispatch {\n    var action: String\n    var branch: String\n    var client_payload: WebhookPayloadRepositoryDispatchClientPayload\n    var repository: PayloadRepository\n    var organization: WebhookPayloadRepositoryDispatchOrganization\n    var sender: WebhookPayloadRepositoryDispatchSender\n    var installation: WebhookPayloadRepositoryDispatchInstallation\n}\n\nexternal interface WebhookPayloadReleaseSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadReleaseReleaseAuthor {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadReleaseRelease {\n    var url: String\n    var assets_url: String\n    var upload_url: String\n    var html_url: String\n    var id: Number\n    var node_id: String\n    var tag_name: String\n    var target_commitish: String\n    var name: Any?\n    var draft: Boolean\n    var author: WebhookPayloadReleaseReleaseAuthor\n    var prerelease: Boolean\n    var created_at: String\n    var published_at: String\n    var assets: Array<Any>\n    var tarball_url: String\n    var zipball_url: String\n    var body: Any?\n}\n\nexternal interface WebhookPayloadRelease {\n    var action: String\n    var release: WebhookPayloadReleaseRelease\n    var repository: PayloadRepository\n    var sender: WebhookPayloadReleaseSender\n}\n\nexternal interface WebhookPayloadPushSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPushPusher {\n    var name: String\n    var email: String\n}\n\nexternal interface WebhookPayloadPush {\n    var ref: String\n    var before: String\n    var after: String\n    var created: Boolean\n    var deleted: Boolean\n    var forced: Boolean\n    var base_ref: Any?\n    var compare: String\n    var commits: Array<Any>\n    var head_commit: Any?\n    var repository: PayloadRepository\n    var pusher: WebhookPayloadPushPusher\n    var sender: WebhookPayloadPushSender\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksStatuses {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksCommits {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksReviewComment {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksReviewComments {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksComments {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksIssue {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksHtml {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinksSelf {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestLinks {\n    var self: WebhookPayloadPullRequestReviewCommentPullRequestLinksSelf\n    var html: WebhookPayloadPullRequestReviewCommentPullRequestLinksHtml\n    var issue: WebhookPayloadPullRequestReviewCommentPullRequestLinksIssue\n    var comments: WebhookPayloadPullRequestReviewCommentPullRequestLinksComments\n    var review_comments: WebhookPayloadPullRequestReviewCommentPullRequestLinksReviewComments\n    var review_comment: WebhookPayloadPullRequestReviewCommentPullRequestLinksReviewComment\n    var commits: WebhookPayloadPullRequestReviewCommentPullRequestLinksCommits\n    var statuses: WebhookPayloadPullRequestReviewCommentPullRequestLinksStatuses\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestBaseRepoOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestBaseRepo {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadPullRequestReviewCommentPullRequestBaseRepoOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var allow_squash_merge: Boolean?\n    var allow_merge_commit: Boolean?\n    var allow_rebase_merge: Boolean?\n    var delete_branch_on_merge: Boolean?\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestBaseUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestBase {\n    var label: String\n    var ref: String\n    var sha: String\n    var user: WebhookPayloadPullRequestReviewCommentPullRequestBaseUser\n    var repo: WebhookPayloadPullRequestReviewCommentPullRequestBaseRepo\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestHeadRepoOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestHeadRepo {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadPullRequestReviewCommentPullRequestHeadRepoOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var allow_squash_merge: Boolean?\n    var allow_merge_commit: Boolean?\n    var allow_rebase_merge: Boolean?\n    var delete_branch_on_merge: Boolean?\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestHeadUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestHead {\n    var label: String\n    var ref: String\n    var sha: String\n    var user: WebhookPayloadPullRequestReviewCommentPullRequestHeadUser\n    var repo: WebhookPayloadPullRequestReviewCommentPullRequestHeadRepo\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequestUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentPullRequest {\n    var url: String\n    var id: Number\n    var node_id: String\n    var html_url: String\n    var diff_url: String\n    var patch_url: String\n    var issue_url: String\n    var number: Number\n    var state: String\n    var locked: Boolean\n    var title: String\n    var user: WebhookPayloadPullRequestReviewCommentPullRequestUser\n    var body: String\n    var created_at: String\n    var updated_at: String\n    var closed_at: Any?\n    var merged_at: Any?\n    var merge_commit_sha: String\n    var assignee: Any?\n    var assignees: Array<Any>\n    var requested_reviewers: Array<Any>\n    var requested_teams: Array<Any>\n    var labels: Array<Any>\n    var milestone: Any?\n    var commits_url: String\n    var review_comments_url: String\n    var review_comment_url: String\n    var comments_url: String\n    var statuses_url: String\n    var head: WebhookPayloadPullRequestReviewCommentPullRequestHead\n    var base: WebhookPayloadPullRequestReviewCommentPullRequestBase\n    var _links: WebhookPayloadPullRequestReviewCommentPullRequestLinks\n    var author_association: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentCommentLinksPullRequest {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentCommentLinksHtml {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentCommentLinksSelf {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentCommentLinks {\n    var self: WebhookPayloadPullRequestReviewCommentCommentLinksSelf\n    var html: WebhookPayloadPullRequestReviewCommentCommentLinksHtml\n    var pull_request: WebhookPayloadPullRequestReviewCommentCommentLinksPullRequest\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentCommentUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewCommentComment {\n    var url: String\n    var pull_request_review_id: Number\n    var id: Number\n    var node_id: String\n    var diff_hunk: String\n    var path: String\n    var position: Number\n    var original_position: Number\n    var commit_id: String\n    var original_commit_id: String\n    var user: WebhookPayloadPullRequestReviewCommentCommentUser\n    var body: String\n    var created_at: String\n    var updated_at: String\n    var html_url: String\n    var pull_request_url: String\n    var author_association: String\n    var _links: WebhookPayloadPullRequestReviewCommentCommentLinks\n}\n\nexternal interface WebhookPayloadPullRequestReviewComment {\n    var action: String\n    var comment: WebhookPayloadPullRequestReviewCommentComment\n    var pull_request: WebhookPayloadPullRequestReviewCommentPullRequest\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPullRequestReviewCommentSender\n}\n\nexternal interface WebhookPayloadPullRequestReviewSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksStatuses {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksCommits {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksReviewComment {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksReviewComments {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksComments {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksIssue {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksHtml {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinksSelf {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestLinks {\n    var self: WebhookPayloadPullRequestReviewPullRequestLinksSelf\n    var html: WebhookPayloadPullRequestReviewPullRequestLinksHtml\n    var issue: WebhookPayloadPullRequestReviewPullRequestLinksIssue\n    var comments: WebhookPayloadPullRequestReviewPullRequestLinksComments\n    var review_comments: WebhookPayloadPullRequestReviewPullRequestLinksReviewComments\n    var review_comment: WebhookPayloadPullRequestReviewPullRequestLinksReviewComment\n    var commits: WebhookPayloadPullRequestReviewPullRequestLinksCommits\n    var statuses: WebhookPayloadPullRequestReviewPullRequestLinksStatuses\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestBaseRepoOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestBaseRepo {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadPullRequestReviewPullRequestBaseRepoOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var allow_squash_merge: Boolean?\n    var allow_merge_commit: Boolean?\n    var allow_rebase_merge: Boolean?\n    var delete_branch_on_merge: Boolean?\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestBaseUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestBase {\n    var label: String\n    var ref: String\n    var sha: String\n    var user: WebhookPayloadPullRequestReviewPullRequestBaseUser\n    var repo: WebhookPayloadPullRequestReviewPullRequestBaseRepo\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestHeadRepoOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestHeadRepo {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadPullRequestReviewPullRequestHeadRepoOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var allow_squash_merge: Boolean?\n    var allow_merge_commit: Boolean?\n    var allow_rebase_merge: Boolean?\n    var delete_branch_on_merge: Boolean?\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestHeadUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestHead {\n    var label: String\n    var ref: String\n    var sha: String\n    var user: WebhookPayloadPullRequestReviewPullRequestHeadUser\n    var repo: WebhookPayloadPullRequestReviewPullRequestHeadRepo\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequestUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewPullRequest {\n    var url: String\n    var id: Number\n    var node_id: String\n    var html_url: String\n    var diff_url: String\n    var patch_url: String\n    var issue_url: String\n    var number: Number\n    var state: String\n    var locked: Boolean\n    var title: String\n    var user: WebhookPayloadPullRequestReviewPullRequestUser\n    var body: String\n    var created_at: String\n    var updated_at: String\n    var closed_at: Any?\n    var merged_at: Any?\n    var merge_commit_sha: String\n    var assignee: Any?\n    var assignees: Array<Any>\n    var requested_reviewers: Array<Any>\n    var requested_teams: Array<Any>\n    var labels: Array<Any>\n    var milestone: Any?\n    var commits_url: String\n    var review_comments_url: String\n    var review_comment_url: String\n    var comments_url: String\n    var statuses_url: String\n    var head: WebhookPayloadPullRequestReviewPullRequestHead\n    var base: WebhookPayloadPullRequestReviewPullRequestBase\n    var _links: WebhookPayloadPullRequestReviewPullRequestLinks\n    var author_association: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewReviewLinksPullRequest {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewReviewLinksHtml {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestReviewReviewLinks {\n    var html: WebhookPayloadPullRequestReviewReviewLinksHtml\n    var pull_request: WebhookPayloadPullRequestReviewReviewLinksPullRequest\n}\n\nexternal interface WebhookPayloadPullRequestReviewReviewUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestReviewReview {\n    var id: Number\n    var node_id: String\n    var user: WebhookPayloadPullRequestReviewReviewUser\n    var body: Any?\n    var commit_id: String\n    var submitted_at: String\n    var state: String\n    var html_url: String\n    var pull_request_url: String\n    var author_association: String\n    var _links: WebhookPayloadPullRequestReviewReviewLinks\n}\n\nexternal interface WebhookPayloadPullRequestReview {\n    var action: String\n    var review: WebhookPayloadPullRequestReviewReview\n    var pull_request: WebhookPayloadPullRequestReviewPullRequest\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPullRequestReviewSender\n}\n\nexternal interface WebhookPayloadPullRequestLabel {\n    var id: Number\n    var node_id: String\n    var url: String\n    var name: String\n    var color: String\n    var default: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestMilestoneCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface `T$75` {\n    var url: String\n    var html_url: String\n    var labels_url: String\n    var id: Number\n    var node_id: String\n    var number: Number\n    var title: String\n    var description: String\n    var creator: WebhookPayloadPullRequestPullRequestMilestoneCreator\n    var open_issues: Number\n    var closed_issues: Number\n    var state: String\n    var created_at: String\n    var updated_at: String\n    var due_on: String\n    var closed_at: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLabelsItem {\n    var id: Number\n    var node_id: String\n    var url: String\n    var name: String\n    var color: String\n    var default: Boolean\n}\n\nexternal interface `T$76` {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestInstallation {\n    var id: Number\n    var node_id: String\n}\n\nexternal interface WebhookPayloadPullRequestAssignee {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestAssigneesItem {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksStatuses {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksCommits {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksReviewComment {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksReviewComments {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksComments {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksIssue {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksHtml {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinksSelf {\n    var href: String\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestLinks {\n    var self: WebhookPayloadPullRequestPullRequestLinksSelf\n    var html: WebhookPayloadPullRequestPullRequestLinksHtml\n    var issue: WebhookPayloadPullRequestPullRequestLinksIssue\n    var comments: WebhookPayloadPullRequestPullRequestLinksComments\n    var review_comments: WebhookPayloadPullRequestPullRequestLinksReviewComments\n    var review_comment: WebhookPayloadPullRequestPullRequestLinksReviewComment\n    var commits: WebhookPayloadPullRequestPullRequestLinksCommits\n    var statuses: WebhookPayloadPullRequestPullRequestLinksStatuses\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestBaseRepoOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestBaseRepo {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadPullRequestPullRequestBaseRepoOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String?\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var allow_squash_merge: Boolean?\n    var allow_merge_commit: Boolean?\n    var allow_rebase_merge: Boolean?\n    var delete_branch_on_merge: Boolean?\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestBaseUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestBase {\n    var label: String\n    var ref: String\n    var sha: String\n    var user: WebhookPayloadPullRequestPullRequestBaseUser\n    var repo: WebhookPayloadPullRequestPullRequestBaseRepo\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestHeadRepoOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestHeadRepo {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadPullRequestPullRequestHeadRepoOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String?\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var allow_squash_merge: Boolean?\n    var allow_merge_commit: Boolean?\n    var allow_rebase_merge: Boolean?\n    var delete_branch_on_merge: Boolean?\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestHeadUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestHead {\n    var label: String\n    var ref: String\n    var sha: String\n    var user: WebhookPayloadPullRequestPullRequestHeadUser\n    var repo: WebhookPayloadPullRequestPullRequestHeadRepo\n}\n\nexternal interface WebhookPayloadPullRequestPullRequestUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPullRequestPullRequest {\n    var url: String\n    var id: Number\n    var node_id: String\n    var html_url: String\n    var diff_url: String\n    var patch_url: String\n    var issue_url: String\n    var number: Number\n    var state: String\n    var locked: Boolean\n    var title: String\n    var user: WebhookPayloadPullRequestPullRequestUser\n    var body: String\n    var created_at: String\n    var updated_at: String\n    var closed_at: String?\n    var merged_at: Any?\n    var merge_commit_sha: String?\n    var assignee: `T$76`?\n    var assignees: Array<WebhookPayloadPullRequestPullRequestAssigneesItem>\n    var requested_reviewers: Array<Any>\n    var requested_teams: Array<Any>\n    var labels: Array<WebhookPayloadPullRequestPullRequestLabelsItem>\n    var milestone: `T$75`?\n    var commits_url: String\n    var review_comments_url: String\n    var review_comment_url: String\n    var comments_url: String\n    var statuses_url: String\n    var head: WebhookPayloadPullRequestPullRequestHead\n    var base: WebhookPayloadPullRequestPullRequestBase\n    var _links: WebhookPayloadPullRequestPullRequestLinks\n    var author_association: String\n    var draft: Boolean\n    var merged: Boolean\n    var mergeable: Boolean?\n    var rebaseable: Boolean?\n    var mergeable_state: String\n    var merged_by: Any?\n    var comments: Number\n    var review_comments: Number\n    var maintainer_can_modify: Boolean\n    var commits: Number\n    var additions: Number\n    var deletions: Number\n    var changed_files: Number\n}\n\nexternal interface WebhookPayloadPullRequest {\n    var action: String\n    var number: Number\n    var pull_request: WebhookPayloadPullRequestPullRequest\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPullRequestSender\n    var assignee: WebhookPayloadPullRequestAssignee?\n    var installation: WebhookPayloadPullRequestInstallation?\n    var label: WebhookPayloadPullRequestLabel?\n}\n\nexternal interface WebhookPayloadPublicSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPublic {\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPublicSender\n}\n\nexternal interface WebhookPayloadProjectSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadProjectProjectCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadProjectProject {\n    var owner_url: String\n    var url: String\n    var html_url: String\n    var columns_url: String\n    var id: Number\n    var node_id: String\n    var name: String\n    var body: String\n    var number: Number\n    var state: String\n    var creator: WebhookPayloadProjectProjectCreator\n    var created_at: String\n    var updated_at: String\n}\n\nexternal interface WebhookPayloadProject {\n    var action: String\n    var project: WebhookPayloadProjectProject\n    var repository: PayloadRepository\n    var sender: WebhookPayloadProjectSender\n}\n\nexternal interface WebhookPayloadProjectColumnSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadProjectColumnProjectColumn {\n    var url: String\n    var project_url: String\n    var cards_url: String\n    var id: Number\n    var node_id: String\n    var name: String\n    var created_at: String\n    var updated_at: String\n}\n\nexternal interface WebhookPayloadProjectColumn {\n    var action: String\n    var project_column: WebhookPayloadProjectColumnProjectColumn\n    var repository: PayloadRepository\n    var sender: WebhookPayloadProjectColumnSender\n}\n\nexternal interface WebhookPayloadProjectCardSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadProjectCardProjectCardCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadProjectCardProjectCard {\n    var url: String\n    var project_url: String\n    var column_url: String\n    var column_id: Number\n    var id: Number\n    var node_id: String\n    var note: String\n    var archived: Boolean\n    var creator: WebhookPayloadProjectCardProjectCardCreator\n    var created_at: String\n    var updated_at: String\n}\n\nexternal interface WebhookPayloadProjectCard {\n    var action: String\n    var project_card: WebhookPayloadProjectCardProjectCard\n    var repository: PayloadRepository\n    var sender: WebhookPayloadProjectCardSender\n}\n\nexternal interface WebhookPayloadPingSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPingHookLastResponse {\n    var code: Any?\n    var status: String\n    var message: Any?\n}\n\nexternal interface WebhookPayloadPingHookConfig {\n    var content_type: String\n    var url: String\n    var insecure_ssl: String\n}\n\nexternal interface WebhookPayloadPingHook {\n    var type: String\n    var id: Number\n    var name: String\n    var active: Boolean\n    var events: Array<String>\n    var config: WebhookPayloadPingHookConfig\n    var updated_at: String\n    var created_at: String\n    var url: String\n    var test_url: String\n    var ping_url: String\n    var last_response: WebhookPayloadPingHookLastResponse\n}\n\nexternal interface WebhookPayloadPing {\n    var zen: String\n    var hook_id: Number\n    var hook: WebhookPayloadPingHook\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPingSender\n}\n\nexternal interface WebhookPayloadPageBuildSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPageBuildBuildPusher {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPageBuildBuildError {\n    var message: Any?\n}\n\nexternal interface WebhookPayloadPageBuildBuild {\n    var url: String\n    var status: String\n    var error: WebhookPayloadPageBuildBuildError\n    var pusher: WebhookPayloadPageBuildBuildPusher\n    var commit: String\n    var duration: Number\n    var created_at: String\n    var updated_at: String\n}\n\nexternal interface WebhookPayloadPageBuild {\n    var id: Number\n    var build: WebhookPayloadPageBuildBuild\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPageBuildSender\n}\n\nexternal interface WebhookPayloadPackageSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPackagePackageRegistry {\n    var about_url: String\n    var name: String\n    var type: String\n    var url: String\n    var vendor: String\n}\n\nexternal interface WebhookPayloadPackagePackagePackageVersionAuthor {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPackagePackagePackageVersionPackageFilesItem {\n    var download_url: String\n    var id: Number\n    var name: String\n    var sha256: String\n    var sha1: String\n    var md5: String\n    var content_type: String\n    var state: String\n    var size: Number\n    var created_at: String\n    var updated_at: String\n}\n\nexternal interface WebhookPayloadPackagePackagePackageVersionReleaseAuthor {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPackagePackagePackageVersionRelease {\n    var url: String\n    var html_url: String\n    var id: Number\n    var tag_name: String\n    var target_commitish: String\n    var name: String\n    var draft: Boolean\n    var author: WebhookPayloadPackagePackagePackageVersionReleaseAuthor\n    var prerelease: Boolean\n    var created_at: String\n    var published_at: String\n}\n\nexternal interface WebhookPayloadPackagePackagePackageVersion {\n    var id: Number\n    var version: String\n    var summary: String\n    var body: String\n    var body_html: String\n    var release: WebhookPayloadPackagePackagePackageVersionRelease\n    var manifest: String\n    var html_url: String\n    var tag_name: String\n    var target_commitish: String\n    var target_oid: String\n    var draft: Boolean\n    var prerelease: Boolean\n    var created_at: String\n    var updated_at: String\n    var metadata: Array<Any>\n    var package_files: Array<WebhookPayloadPackagePackagePackageVersionPackageFilesItem>\n    var author: WebhookPayloadPackagePackagePackageVersionAuthor\n    var installation_command: String\n}\n\nexternal interface WebhookPayloadPackagePackageOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadPackagePackage {\n    var id: Number\n    var name: String\n    var package_type: String\n    var html_url: String\n    var created_at: String\n    var updated_at: String\n    var owner: WebhookPayloadPackagePackageOwner\n    var package_version: WebhookPayloadPackagePackagePackageVersion\n    var registry: WebhookPayloadPackagePackageRegistry\n}\n\nexternal interface WebhookPayloadPackage {\n    var action: String\n    var `package`: WebhookPayloadPackagePackage\n    var repository: PayloadRepository\n    var sender: WebhookPayloadPackageSender\n}\n\nexternal interface WebhookPayloadOrgBlockSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadOrgBlockOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadOrgBlockBlockedUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadOrgBlock {\n    var action: String\n    var blocked_user: WebhookPayloadOrgBlockBlockedUser\n    var organization: WebhookPayloadOrgBlockOrganization\n    var sender: WebhookPayloadOrgBlockSender\n}\n\nexternal interface WebhookPayloadOrganizationSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadOrganizationOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadOrganizationMembershipUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadOrganizationMembership {\n    var url: String\n    var state: String\n    var role: String\n    var organization_url: String\n    var user: WebhookPayloadOrganizationMembershipUser\n}\n\nexternal interface WebhookPayloadOrganization {\n    var action: String\n    var membership: WebhookPayloadOrganizationMembership\n    var organization: WebhookPayloadOrganizationOrganization\n    var sender: WebhookPayloadOrganizationSender\n}\n\nexternal interface WebhookPayloadMilestoneSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMilestoneMilestoneCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMilestoneMilestone {\n    var url: String\n    var html_url: String\n    var labels_url: String\n    var id: Number\n    var node_id: String\n    var number: Number\n    var title: String\n    var description: String\n    var creator: WebhookPayloadMilestoneMilestoneCreator\n    var open_issues: Number\n    var closed_issues: Number\n    var state: String\n    var created_at: String\n    var updated_at: String\n    var due_on: String\n    var closed_at: String?\n}\n\nexternal interface WebhookPayloadMilestone {\n    var action: String\n    var milestone: WebhookPayloadMilestoneMilestone\n    var repository: PayloadRepository\n    var sender: WebhookPayloadMilestoneSender\n}\n\nexternal interface WebhookPayloadMetaSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMetaHookConfig {\n    var content_type: String\n    var insecure_ssl: String\n    var url: String\n}\n\nexternal interface WebhookPayloadMetaHook {\n    var type: String\n    var id: Number\n    var name: String\n    var active: Boolean\n    var events: Array<String>\n    var config: WebhookPayloadMetaHookConfig\n    var updated_at: String\n    var created_at: String\n}\n\nexternal interface WebhookPayloadMeta {\n    var action: String\n    var hook_id: Number\n    var hook: WebhookPayloadMetaHook\n    var repository: PayloadRepository\n    var sender: WebhookPayloadMetaSender\n}\n\nexternal interface WebhookPayloadMembershipOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadMembershipTeam {\n    var name: String\n    var id: Number\n    var node_id: String\n    var slug: String\n    var description: String\n    var privacy: String\n    var url: String\n    var html_url: String\n    var members_url: String\n    var repositories_url: String\n    var permission: String\n}\n\nexternal interface WebhookPayloadMembershipSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMembershipMember {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMembership {\n    var action: String\n    var scope: String\n    var member: WebhookPayloadMembershipMember\n    var sender: WebhookPayloadMembershipSender\n    var team: WebhookPayloadMembershipTeam\n    var organization: WebhookPayloadMembershipOrganization\n}\n\nexternal interface WebhookPayloadMemberChangesPermission {\n    var from: String\n}\n\nexternal interface WebhookPayloadMemberChanges {\n    var permission: WebhookPayloadMemberChangesPermission\n}\n\nexternal interface WebhookPayloadMemberSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMemberMember {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadMember {\n    var action: String\n    var member: WebhookPayloadMemberMember\n    var repository: PayloadRepository\n    var sender: WebhookPayloadMemberSender\n    var changes: WebhookPayloadMemberChanges?\n}\n\nexternal interface WebhookPayloadMarketplacePurchasePreviousMarketplacePurchasePlan {\n    var id: Number\n    var name: String\n    var description: String\n    var monthly_price_in_cents: Number\n    var yearly_price_in_cents: Number\n    var price_model: String\n    var has_free_trial: Boolean\n    var unit_name: String\n    var bullets: Array<String>\n}\n\nexternal interface WebhookPayloadMarketplacePurchasePreviousMarketplacePurchaseAccount {\n    var type: String\n    var id: Number\n    var login: String\n    var organization_billing_email: String\n}\n\nexternal interface WebhookPayloadMarketplacePurchasePreviousMarketplacePurchase {\n    var account: WebhookPayloadMarketplacePurchasePreviousMarketplacePurchaseAccount\n    var billing_cycle: String\n    var on_free_trial: Boolean\n    var free_trial_ends_on: Any?\n    var unit_count: Number\n    var plan: WebhookPayloadMarketplacePurchasePreviousMarketplacePurchasePlan\n}\n\nexternal interface WebhookPayloadMarketplacePurchaseMarketplacePurchasePlan {\n    var id: Number\n    var name: String\n    var description: String\n    var monthly_price_in_cents: Number\n    var yearly_price_in_cents: Number\n    var price_model: String\n    var has_free_trial: Boolean\n    var unit_name: String?\n    var bullets: Array<String>\n}\n\nexternal interface WebhookPayloadMarketplacePurchaseMarketplacePurchaseAccount {\n    var type: String\n    var id: Number\n    var login: String\n    var organization_billing_email: String\n}\n\nexternal interface WebhookPayloadMarketplacePurchaseMarketplacePurchase {\n    var account: WebhookPayloadMarketplacePurchaseMarketplacePurchaseAccount\n    var billing_cycle: String\n    var unit_count: Number\n    var on_free_trial: Boolean\n    var free_trial_ends_on: Any?\n    var next_billing_date: String\n    var plan: WebhookPayloadMarketplacePurchaseMarketplacePurchasePlan\n}\n\nexternal interface WebhookPayloadMarketplacePurchaseSender {\n    var login: String\n    var id: Number\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n    var email: String\n}\n\nexternal interface WebhookPayloadMarketplacePurchase {\n    var action: String\n    var effective_date: String\n    var sender: WebhookPayloadMarketplacePurchaseSender\n    var marketplace_purchase: WebhookPayloadMarketplacePurchaseMarketplacePurchase\n    var previous_marketplace_purchase: WebhookPayloadMarketplacePurchasePreviousMarketplacePurchase?\n}\n\nexternal interface WebhookPayloadLabelChangesColor {\n    var from: String\n}\n\nexternal interface WebhookPayloadLabelChanges {\n    var color: WebhookPayloadLabelChangesColor\n}\n\nexternal interface WebhookPayloadLabelSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadLabelLabel {\n    var id: Number\n    var node_id: String\n    var url: String\n    var name: String\n    var color: String\n    var default: Boolean\n}\n\nexternal interface WebhookPayloadLabel {\n    var action: String\n    var label: WebhookPayloadLabelLabel\n    var repository: PayloadRepository\n    var sender: WebhookPayloadLabelSender\n    var changes: WebhookPayloadLabelChanges?\n}\n\nexternal interface WebhookPayloadIssuesLabel {\n    var id: Number\n    var node_id: String\n    var url: String\n    var name: String\n    var color: String\n    var default: Boolean\n}\n\nexternal interface WebhookPayloadIssuesIssuePullRequest {\n    var url: String\n    var html_url: String\n    var diff_url: String\n    var patch_url: String\n}\n\nexternal interface WebhookPayloadIssuesAssignee {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssuesSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssuesChanges\n\nexternal interface WebhookPayloadIssuesIssueMilestoneCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface `T$77` {\n    var url: String\n    var html_url: String\n    var labels_url: String\n    var id: Number\n    var node_id: String\n    var number: Number\n    var title: String\n    var description: String\n    var creator: WebhookPayloadIssuesIssueMilestoneCreator\n    var open_issues: Number\n    var closed_issues: Number\n    var state: String\n    var created_at: String\n    var updated_at: String\n    var due_on: String\n    var closed_at: String\n}\n\nexternal interface WebhookPayloadIssuesIssueAssigneesItem {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssuesIssueLabelsItem {\n    var id: Number\n    var node_id: String\n    var url: String\n    var name: String\n    var color: String\n    var default: Boolean\n}\n\nexternal interface WebhookPayloadIssuesIssueUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssuesIssue {\n    var url: String\n    var repository_url: String\n    var labels_url: String\n    var comments_url: String\n    var events_url: String\n    var html_url: String\n    var id: Number\n    var node_id: String\n    var number: Number\n    var title: String\n    var user: WebhookPayloadIssuesIssueUser\n    var labels: Array<WebhookPayloadIssuesIssueLabelsItem>\n    var state: String\n    var locked: Boolean\n    var assignee: `T$76`?\n    var assignees: Array<WebhookPayloadIssuesIssueAssigneesItem>\n    var milestone: `T$77`?\n    var comments: Number\n    var created_at: String\n    var updated_at: String\n    var closed_at: Any?\n    var author_association: String\n    var body: String\n    var pull_request: WebhookPayloadIssuesIssuePullRequest?\n}\n\nexternal interface WebhookPayloadIssues {\n    var action: String\n    var issue: WebhookPayloadIssuesIssue\n    var changes: WebhookPayloadIssuesChanges?\n    var repository: PayloadRepository\n    var sender: WebhookPayloadIssuesSender\n    var assignee: WebhookPayloadIssuesAssignee?\n    var label: WebhookPayloadIssuesLabel?\n}\n\nexternal interface WebhookPayloadIssueCommentChangesBody {\n    var from: String\n}\n\nexternal interface WebhookPayloadIssueCommentChanges {\n    var body: WebhookPayloadIssueCommentChangesBody\n}\n\nexternal interface WebhookPayloadIssueCommentSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentCommentUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentComment {\n    var url: String\n    var html_url: String\n    var issue_url: String\n    var id: Number\n    var node_id: String\n    var user: WebhookPayloadIssueCommentCommentUser\n    var created_at: String\n    var updated_at: String\n    var author_association: String\n    var body: String\n}\n\nexternal interface WebhookPayloadIssueCommentIssueMilestoneCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentIssueMilestone {\n    var url: String\n    var html_url: String\n    var labels_url: String\n    var id: Number\n    var node_id: String\n    var number: Number\n    var title: String\n    var description: String\n    var creator: WebhookPayloadIssueCommentIssueMilestoneCreator\n    var open_issues: Number\n    var closed_issues: Number\n    var state: String\n    var created_at: String\n    var updated_at: String\n    var due_on: String\n    var closed_at: String\n}\n\nexternal interface WebhookPayloadIssueCommentIssueAssigneesItem {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentIssueAssignee {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentIssueLabelsItem {\n    var id: Number\n    var node_id: String\n    var url: String\n    var name: String\n    var color: String\n    var default: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentIssueUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadIssueCommentIssue {\n    var url: String\n    var repository_url: String\n    var labels_url: String\n    var comments_url: String\n    var events_url: String\n    var html_url: String\n    var id: Number\n    var node_id: String\n    var number: Number\n    var title: String\n    var user: WebhookPayloadIssueCommentIssueUser\n    var labels: Array<WebhookPayloadIssueCommentIssueLabelsItem>\n    var state: String\n    var locked: Boolean\n    var assignee: WebhookPayloadIssueCommentIssueAssignee\n    var assignees: Array<WebhookPayloadIssueCommentIssueAssigneesItem>\n    var milestone: WebhookPayloadIssueCommentIssueMilestone\n    var comments: Number\n    var created_at: String\n    var updated_at: String\n    var closed_at: Any?\n    var author_association: String\n    var body: String\n}\n\nexternal interface WebhookPayloadIssueComment {\n    var action: String\n    var issue: WebhookPayloadIssueCommentIssue\n    var comment: WebhookPayloadIssueCommentComment\n    var repository: PayloadRepository\n    var sender: WebhookPayloadIssueCommentSender\n    var changes: WebhookPayloadIssueCommentChanges?\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesRepositoriesRemovedItem {\n    var id: Number\n    var name: String\n    var full_name: String\n    var private: Boolean\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesRepositoriesAddedItem {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesInstallationPermissions {\n    var administration: String?\n    var statuses: String?\n    var repository_projects: String?\n    var repository_hooks: String?\n    var pull_requests: String?\n    var pages: String?\n    var issues: String\n    var deployments: String?\n    var contents: String\n    var checks: String?\n    var metadata: String\n    var vulnerability_alerts: String?\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesInstallationAccount {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesInstallation {\n    var id: Number\n    var account: WebhookPayloadInstallationRepositoriesInstallationAccount\n    var repository_selection: String\n    var access_tokens_url: String\n    var repositories_url: String\n    var html_url: String\n    var app_id: Number\n    var target_id: Number\n    var target_type: String\n    var permissions: WebhookPayloadInstallationRepositoriesInstallationPermissions\n    var events: Array<String>\n    var created_at: Number\n    var updated_at: Number\n    var single_file_name: String?\n}\n\nexternal interface WebhookPayloadInstallationRepositories {\n    var action: String\n    var installation: WebhookPayloadInstallationRepositoriesInstallation\n    var repository_selection: String\n    var repositories_added: Array<WebhookPayloadInstallationRepositoriesRepositoriesAddedItem>\n    var repositories_removed: Array<WebhookPayloadInstallationRepositoriesRepositoriesRemovedItem>\n    var sender: WebhookPayloadInstallationRepositoriesSender\n}\n\nexternal interface WebhookPayloadInstallationSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadInstallationRepositoriesItem {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n}\n\nexternal interface WebhookPayloadInstallationInstallationPermissions {\n    var metadata: String\n    var contents: String\n    var issues: String\n    var administration: String?\n    var checks: String?\n    var deployments: String?\n    var pages: String?\n    var pull_requests: String?\n    var repository_hooks: String?\n    var repository_projects: String?\n    var statuses: String?\n    var vulnerability_alerts: String?\n}\n\nexternal interface WebhookPayloadInstallationInstallationAccount {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadInstallationInstallation {\n    var id: Number\n    var account: WebhookPayloadInstallationInstallationAccount\n    var repository_selection: String\n    var access_tokens_url: String\n    var repositories_url: String\n    var html_url: String\n    var app_id: Number\n    var target_id: Number\n    var target_type: String\n    var permissions: WebhookPayloadInstallationInstallationPermissions\n    var events: Array<String>\n    var created_at: Number\n    var updated_at: Number\n    var single_file_name: String?\n}\n\nexternal interface WebhookPayloadInstallation {\n    var action: String\n    var installation: WebhookPayloadInstallationInstallation\n    var repositories: Array<WebhookPayloadInstallationRepositoriesItem>\n    var sender: WebhookPayloadInstallationSender\n}\n\nexternal interface WebhookPayloadGollumSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadGollumPagesItem {\n    var page_name: String\n    var title: String\n    var summary: Any?\n    var action: String\n    var sha: String\n    var html_url: String\n}\n\nexternal interface WebhookPayloadGollum {\n    var pages: Array<WebhookPayloadGollumPagesItem>\n    var repository: PayloadRepository\n    var sender: WebhookPayloadGollumSender\n}\n\nexternal interface WebhookPayloadGithubAppAuthorizationSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadGithubAppAuthorization {\n    var action: String\n    var sender: WebhookPayloadGithubAppAuthorizationSender\n}\n\nexternal interface WebhookPayloadForkSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadForkForkeeOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadForkForkee {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: WebhookPayloadForkForkeeOwner\n    var html_url: String\n    var description: Any?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: String\n    var updated_at: String\n    var pushed_at: String\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: Any?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: Any?\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var public: Boolean\n}\n\nexternal interface WebhookPayloadFork {\n    var forkee: WebhookPayloadForkForkee\n    var repository: PayloadRepository\n    var sender: WebhookPayloadForkSender\n}\n\nexternal interface WebhookPayloadDeploymentStatusSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDeploymentStatusDeploymentCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDeploymentStatusDeploymentPayload\n\nexternal interface WebhookPayloadDeploymentStatusDeployment {\n    var url: String\n    var id: Number\n    var node_id: String\n    var sha: String\n    var ref: String\n    var task: String\n    var payload: WebhookPayloadDeploymentStatusDeploymentPayload\n    var original_environment: String\n    var environment: String\n    var description: Any?\n    var creator: WebhookPayloadDeploymentStatusDeploymentCreator\n    var created_at: String\n    var updated_at: String\n    var statuses_url: String\n    var repository_url: String\n}\n\nexternal interface WebhookPayloadDeploymentStatusDeploymentStatusCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDeploymentStatusDeploymentStatus {\n    var url: String\n    var id: Number\n    var node_id: String\n    var state: String\n    var creator: WebhookPayloadDeploymentStatusDeploymentStatusCreator\n    var description: String\n    var environment: String\n    var target_url: String\n    var created_at: String\n    var updated_at: String\n    var deployment_url: String\n    var repository_url: String\n}\n\nexternal interface WebhookPayloadDeploymentStatus {\n    var action: String\n    var deployment_status: WebhookPayloadDeploymentStatusDeploymentStatus\n    var deployment: WebhookPayloadDeploymentStatusDeployment\n    var repository: PayloadRepository\n    var sender: WebhookPayloadDeploymentStatusSender\n}\n\nexternal interface WebhookPayloadDeploymentSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDeploymentDeploymentCreator {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDeploymentDeploymentPayload\n\nexternal interface WebhookPayloadDeploymentDeployment {\n    var url: String\n    var id: Number\n    var node_id: String\n    var sha: String\n    var ref: String\n    var task: String\n    var payload: WebhookPayloadDeploymentDeploymentPayload\n    var original_environment: String\n    var environment: String\n    var description: Any?\n    var creator: WebhookPayloadDeploymentDeploymentCreator\n    var created_at: String\n    var updated_at: String\n    var statuses_url: String\n    var repository_url: String\n}\n\nexternal interface WebhookPayloadDeployment {\n    var action: String\n    var deployment: WebhookPayloadDeploymentDeployment\n    var repository: PayloadRepository\n    var sender: WebhookPayloadDeploymentSender\n}\n\nexternal interface WebhookPayloadDeployKeySender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDeployKeyKey {\n    var id: Number\n    var key: String\n    var url: String\n    var title: String\n    var verified: Boolean\n    var created_at: String\n    var read_only: Boolean\n}\n\nexternal interface WebhookPayloadDeployKey {\n    var action: String\n    var key: WebhookPayloadDeployKeyKey\n    var repository: PayloadRepository\n    var sender: WebhookPayloadDeployKeySender\n}\n\nexternal interface WebhookPayloadDeleteSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadDelete {\n    var ref: String\n    var ref_type: String\n    var pusher_type: String\n    var repository: PayloadRepository\n    var sender: WebhookPayloadDeleteSender\n}\n\nexternal interface WebhookPayloadCreateSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCreate {\n    var ref: String\n    var ref_type: String\n    var master_branch: String\n    var description: Any?\n    var pusher_type: String\n    var repository: PayloadRepository\n    var sender: WebhookPayloadCreateSender\n}\n\nexternal interface WebhookPayloadContentReferenceInstallation {\n    var id: Number\n    var node_id: String\n}\n\nexternal interface WebhookPayloadContentReferenceSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadContentReferenceContentReference {\n    var id: Number\n    var node_id: String\n    var reference: String\n}\n\nexternal interface WebhookPayloadContentReference {\n    var action: String\n    var content_reference: WebhookPayloadContentReferenceContentReference\n    var repository: PayloadRepository\n    var sender: WebhookPayloadContentReferenceSender\n    var installation: WebhookPayloadContentReferenceInstallation\n}\n\nexternal interface WebhookPayloadCommitCommentSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCommitCommentCommentUser {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCommitCommentComment {\n    var url: String\n    var html_url: String\n    var id: Number\n    var node_id: String\n    var user: WebhookPayloadCommitCommentCommentUser\n    var position: Any?\n    var line: Any?\n    var path: Any?\n    var commit_id: String\n    var created_at: String\n    var updated_at: String\n    var author_association: String\n    var body: String\n}\n\nexternal interface WebhookPayloadCommitComment {\n    var action: String\n    var comment: WebhookPayloadCommitCommentComment\n    var repository: PayloadRepository\n    var sender: WebhookPayloadCommitCommentSender\n}\n\nexternal interface WebhookPayloadCheckSuiteInstallation {\n    var id: Number\n    var node_id: String\n}\n\nexternal interface WebhookPayloadCheckSuiteSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuiteHeadCommitCommitter {\n    var name: String\n    var email: String\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuiteHeadCommitAuthor {\n    var name: String\n    var email: String\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuiteHeadCommit {\n    var id: String\n    var tree_id: String\n    var message: String\n    var timestamp: String\n    var author: WebhookPayloadCheckSuiteCheckSuiteHeadCommitAuthor\n    var committer: WebhookPayloadCheckSuiteCheckSuiteHeadCommitCommitter\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuiteAppPermissions {\n    var administration: String\n    var checks: String\n    var contents: String\n    var deployments: String\n    var issues: String\n    var members: String\n    var metadata: String\n    var organization_administration: String\n    var organization_hooks: String\n    var organization_plan: String\n    var organization_projects: String\n    var organization_user_blocking: String\n    var pages: String\n    var pull_requests: String\n    var repository_hooks: String\n    var repository_projects: String\n    var statuses: String\n    var team_discussions: String\n    var vulnerability_alerts: String\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuiteAppOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuiteApp {\n    var id: Number\n    var node_id: String\n    var owner: WebhookPayloadCheckSuiteCheckSuiteAppOwner\n    var name: String\n    var description: String\n    var external_url: String\n    var html_url: String\n    var created_at: String\n    var updated_at: String\n    var permissions: WebhookPayloadCheckSuiteCheckSuiteAppPermissions\n    var events: Array<Any>\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuitePullRequestsItemBaseRepo {\n    var id: Number\n    var url: String\n    var name: String\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuitePullRequestsItemBase {\n    var ref: String\n    var sha: String\n    var repo: WebhookPayloadCheckSuiteCheckSuitePullRequestsItemBaseRepo\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuitePullRequestsItemHeadRepo {\n    var id: Number\n    var url: String\n    var name: String\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuitePullRequestsItemHead {\n    var ref: String\n    var sha: String\n    var repo: WebhookPayloadCheckSuiteCheckSuitePullRequestsItemHeadRepo\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuitePullRequestsItem {\n    var url: String\n    var id: Number\n    var number: Number\n    var head: WebhookPayloadCheckSuiteCheckSuitePullRequestsItemHead\n    var base: WebhookPayloadCheckSuiteCheckSuitePullRequestsItemBase\n}\n\nexternal interface WebhookPayloadCheckSuiteCheckSuite {\n    var id: Number\n    var node_id: String\n    var head_branch: String\n    var head_sha: String\n    var status: String\n    var conclusion: String?\n    var url: String\n    var before: String\n    var after: String\n    var pull_requests: Array<WebhookPayloadCheckSuiteCheckSuitePullRequestsItem>\n    var app: WebhookPayloadCheckSuiteCheckSuiteApp\n    var created_at: String\n    var updated_at: String\n    var latest_check_runs_count: Number\n    var check_runs_url: String\n    var head_commit: WebhookPayloadCheckSuiteCheckSuiteHeadCommit\n}\n\nexternal interface WebhookPayloadCheckSuite {\n    var action: String\n    var check_suite: WebhookPayloadCheckSuiteCheckSuite\n    var repository: PayloadRepository\n    var sender: WebhookPayloadCheckSuiteSender\n    var installation: WebhookPayloadCheckSuiteInstallation?\n}\n\nexternal interface WebhookPayloadCheckRunInstallation {\n    var id: Number\n}\n\nexternal interface WebhookPayloadCheckRunOrganization {\n    var login: String\n    var id: Number\n    var node_id: String\n    var url: String\n    var repos_url: String\n    var events_url: String\n    var hooks_url: String\n    var issues_url: String\n    var members_url: String\n    var public_members_url: String\n    var avatar_url: String\n    var description: String\n}\n\nexternal interface WebhookPayloadCheckRunSender {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface PayloadRepositoryOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n    var name: String?\n    var email: String?\n}\n\nexternal interface PayloadRepository {\n    var id: Number\n    var node_id: String\n    var name: String\n    var full_name: String\n    var private: Boolean\n    var owner: PayloadRepositoryOwner\n    var html_url: String\n    var description: String?\n    var fork: Boolean\n    var url: String\n    var forks_url: String\n    var keys_url: String\n    var collaborators_url: String\n    var teams_url: String\n    var hooks_url: String\n    var issue_events_url: String\n    var events_url: String\n    var assignees_url: String\n    var branches_url: String\n    var tags_url: String\n    var blobs_url: String\n    var git_tags_url: String\n    var git_refs_url: String\n    var trees_url: String\n    var statuses_url: String\n    var languages_url: String\n    var stargazers_url: String\n    var contributors_url: String\n    var subscribers_url: String\n    var subscription_url: String\n    var commits_url: String\n    var git_commits_url: String\n    var comments_url: String\n    var issue_comment_url: String\n    var contents_url: String\n    var compare_url: String\n    var merges_url: String\n    var archive_url: String\n    var downloads_url: String\n    var issues_url: String\n    var pulls_url: String\n    var milestones_url: String\n    var notifications_url: String\n    var labels_url: String\n    var releases_url: String\n    var deployments_url: String\n    var created_at: dynamic /* String | Number */\n    var updated_at: String\n    var pushed_at: dynamic /* String | Number */\n    var git_url: String\n    var ssh_url: String\n    var clone_url: String\n    var svn_url: String\n    var homepage: String?\n    var size: Number\n    var stargazers_count: Number\n    var watchers_count: Number\n    var language: String?\n    var has_issues: Boolean\n    var has_projects: Boolean\n    var has_downloads: Boolean\n    var has_wiki: Boolean\n    var has_pages: Boolean\n    var forks_count: Number\n    var mirror_url: Any?\n    var archived: Boolean\n    var disabled: Boolean?\n    var open_issues_count: Number\n    var license: Any?\n    var forks: Number\n    var open_issues: Number\n    var watchers: Number\n    var default_branch: String\n    var stargazers: Number?\n    var master_branch: String?\n    var permissions: PayloadRepositoryPermissions?\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunPullRequestsItemBaseRepo {\n    var id: Number\n    var url: String\n    var name: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunPullRequestsItemBase {\n    var ref: String\n    var sha: String\n    var repo: WebhookPayloadCheckRunCheckRunPullRequestsItemBaseRepo\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunPullRequestsItemHeadRepo {\n    var id: Number\n    var url: String\n    var name: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunPullRequestsItemHead {\n    var ref: String\n    var sha: String\n    var repo: WebhookPayloadCheckRunCheckRunPullRequestsItemHeadRepo\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunPullRequestsItem {\n    var url: String\n    var id: Number\n    var number: Number\n    var head: WebhookPayloadCheckRunCheckRunPullRequestsItemHead\n    var base: WebhookPayloadCheckRunCheckRunPullRequestsItemBase\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunAppPermissions {\n    var administration: String\n    var checks: String\n    var contents: String\n    var deployments: String\n    var issues: String\n    var members: String\n    var metadata: String\n    var organization_administration: String\n    var organization_hooks: String\n    var organization_plan: String\n    var organization_projects: String\n    var organization_user_blocking: String\n    var pages: String\n    var pull_requests: String\n    var repository_hooks: String\n    var repository_projects: String\n    var statuses: String\n    var team_discussions: String\n    var vulnerability_alerts: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunAppOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunApp {\n    var id: Number\n    var node_id: String\n    var owner: WebhookPayloadCheckRunCheckRunAppOwner\n    var name: String\n    var description: String?\n    var external_url: String\n    var html_url: String\n    var created_at: String\n    var updated_at: String\n    var permissions: WebhookPayloadCheckRunCheckRunAppPermissions?\n    var events: Array<Any>?\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuiteAppPermissions {\n    var administration: String\n    var checks: String\n    var contents: String\n    var deployments: String\n    var issues: String\n    var members: String\n    var metadata: String\n    var organization_administration: String\n    var organization_hooks: String\n    var organization_plan: String\n    var organization_projects: String\n    var organization_user_blocking: String\n    var pages: String\n    var pull_requests: String\n    var repository_hooks: String\n    var repository_projects: String\n    var statuses: String\n    var team_discussions: String\n    var vulnerability_alerts: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuiteAppOwner {\n    var login: String\n    var id: Number\n    var node_id: String\n    var avatar_url: String\n    var gravatar_id: String\n    var url: String\n    var html_url: String\n    var followers_url: String\n    var following_url: String\n    var gists_url: String\n    var starred_url: String\n    var subscriptions_url: String\n    var organizations_url: String\n    var repos_url: String\n    var events_url: String\n    var received_events_url: String\n    var type: String\n    var site_admin: Boolean\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuiteApp {\n    var id: Number\n    var node_id: String\n    var owner: WebhookPayloadCheckRunCheckRunCheckSuiteAppOwner\n    var name: String\n    var description: String?\n    var external_url: String\n    var html_url: String\n    var created_at: String\n    var updated_at: String\n    var permissions: WebhookPayloadCheckRunCheckRunCheckSuiteAppPermissions?\n    var events: Array<Any>?\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemBaseRepo {\n    var id: Number\n    var url: String\n    var name: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemBase {\n    var ref: String\n    var sha: String\n    var repo: WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemBaseRepo\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemHeadRepo {\n    var id: Number\n    var url: String\n    var name: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemHead {\n    var ref: String\n    var sha: String\n    var repo: WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemHeadRepo\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItem {\n    var url: String\n    var id: Number\n    var number: Number\n    var head: WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemHead\n    var base: WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItemBase\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunCheckSuite {\n    var id: Number\n    var node_id: String?\n    var head_branch: String\n    var head_sha: String\n    var status: String\n    var conclusion: String?\n    var url: String\n    var before: String\n    var after: String\n    var pull_requests: Array<WebhookPayloadCheckRunCheckRunCheckSuitePullRequestsItem>\n    var app: WebhookPayloadCheckRunCheckRunCheckSuiteApp\n    var created_at: String\n    var updated_at: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRunOutput {\n    var title: String?\n    var summary: String?\n    var text: String?\n    var annotations_count: Number\n    var annotations_url: String\n}\n\nexternal interface WebhookPayloadCheckRunCheckRun {\n    var id: Number\n    var node_id: String?\n    var head_sha: String\n    var external_id: String\n    var url: String\n    var html_url: String\n    var details_url: String?\n    var status: String\n    var conclusion: String?\n    var started_at: String\n    var completed_at: String?\n    var output: WebhookPayloadCheckRunCheckRunOutput\n    var name: String\n    var check_suite: WebhookPayloadCheckRunCheckRunCheckSuite\n    var app: WebhookPayloadCheckRunCheckRunApp\n    var pull_requests: Array<WebhookPayloadCheckRunCheckRunPullRequestsItem>\n}\n\nexternal interface WebhookPayloadCheckRun {\n    var action: String\n    var check_run: WebhookPayloadCheckRunCheckRun\n    var repository: PayloadRepository\n    var sender: WebhookPayloadCheckRunSender\n    var organization: WebhookPayloadCheckRunOrganization?\n    var installation: WebhookPayloadCheckRunInstallation?\n}\n"
  },
  {
    "path": "wrappers/octokit-webhooks/src/jsMain/kotlin/octokit/webhooks/get-webhook-payload-type-from-event.module_@octokit_webhooks.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\",\n    \"UNUSED_TYPEALIAS_PARAMETER\")\npackage octokit.webhooks.EventPayloads\n\ntypealias GetWebhookPayloadTypeFromEvent<E, T> = Any\n"
  },
  {
    "path": "wrappers/octokit-webhooks/src/jsMain/kotlin/octokit/webhooks/index.module_@octokit_webhooks.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\n\nexternal fun verify(secret: String = definedExternally, eventPayload: Any? = definedExternally, signature: String = definedExternally): Boolean\n"
  },
  {
    "path": "wrappers/octokit-webhooks/src/jsMain/kotlin/octokit/webhooks/types.module_@octokit_webhooks.kt",
    "content": "@file:Suppress(\"INTERFACE_WITH_SUPERCLASS\", \"OVERRIDING_FINAL_MEMBER\", \"RETURN_TYPE_MISMATCH_ON_OVERRIDE\", \"CONFLICTING_OVERLOADS\")\n\n//import tsstdlib.IterableIterator\n\nexternal interface WebhookEvent<T> {\n    var id: String\n    var name: String /* \"check_run\" | \"check_suite\" | \"commit_comment\" | \"content_reference\" | \"create\" | \"delete\" | \"deploy_key\" | \"deployment\" | \"deployment_status\" | \"fork\" | \"github_app_authorization\" | \"gollum\" | \"installation\" | \"installation_repositories\" | \"issue_comment\" | \"issues\" | \"label\" | \"marketplace_purchase\" | \"member\" | \"membership\" | \"meta\" | \"milestone\" | \"organization\" | \"org_block\" | \"package\" | \"page_build\" | \"ping\" | \"project_card\" | \"project_column\" | \"project\" | \"public\" | \"pull_request\" | \"pull_request_review\" | \"pull_request_review_comment\" | \"push\" | \"release\" | \"repository_dispatch\" | \"repository\" | \"repository_import\" | \"repository_vulnerability_alert\" | \"security_advisory\" | \"sponsorship\" | \"star\" | \"status\" | \"team\" | \"team_add\" | \"watch\" | \"workflow_dispatch\" | \"workflow_run\" */\n    var payload: T\n}\n\nexternal interface WebhookEvent__0 : WebhookEvent<Any>\n\nexternal interface Options<T : WebhookEvent__0> {\n    var path: String?\n    var secret: String?\n    var transform: TransformMethod<T>?\n}\n\ntypealias TransformMethod<@Suppress(\"UNUSED_TYPEALIAS_PARAMETER\") T> = (event: WebhookEvent__0) -> dynamic\n\nexternal interface `T$74` {\n    var event: WebhookEvent__0\n}\n\n//external interface WebhookEventHandlerError : AggregateError<Error /* Error & Any & `T$74` */> {\n//    var event: WebhookEvent__0\n//    var errors: Array<Error /* Error & Any & `T$74` */>\n//}\n//\n//open external class AggregateError<T: Error> : tsstdlib.Iterable<T> {\n//    fun iterator(): IterableIterator<T>\n//}\n"
  }
]