├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── CODEOWNERS
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── config.yml
│ ├── feedback.md
│ └── submit_a_request.md
├── PULL_REQUEST_TEMPLATE.md
├── codeql-config.yml
└── workflows
│ ├── codeql.yml
│ ├── development.yml
│ ├── distribution.yml
│ ├── release.yml
│ ├── test.yaml
│ └── validation.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.js
├── AUTHORS
├── LICENSE
├── README.md
├── __tests__
├── .gitignore
├── flags.test.ts
├── install.test._ts
├── testdata
│ ├── .lstn.yaml
│ ├── from_root.yaml
│ ├── monorepo
│ │ ├── package-lock.json
│ │ ├── poetry.lock
│ │ └── sub
│ │ │ └── poetry.lock
│ └── nolockfiles
│ │ └── .gitignore
└── utils.test.ts
├── action.yml
├── devbox.json
├── devbox.lock
├── dist
├── index.js
├── index.js.map
├── licenses.txt
└── sourcemap-register.js
├── docs
└── listendev_pro_jwt_api_key.png
├── jest.config.js
├── package-lock.json
├── package.json
├── reviewpad.yml
├── src
├── constants.ts
├── eavesdrop.ts
├── flags.ts
├── install.ts
├── lstn.ts
├── main.ts
├── state.ts
├── systemctl.ts
└── utils.ts
└── tsconfig.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | # Ignore list
2 | /*
3 |
4 | # Do not ignore these folders:
5 | !__tests__/
6 | !src/
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
2 | module.exports = {
3 | extends: [
4 | 'eslint:recommended',
5 | 'plugin:@typescript-eslint/recommended',
6 | 'plugin:eslint-plugin-jest/recommended',
7 | 'eslint-config-prettier'
8 | ],
9 | parser: '@typescript-eslint/parser',
10 | plugins: ['@typescript-eslint', 'eslint-plugin-node', 'eslint-plugin-jest'],
11 | rules: {
12 | '@typescript-eslint/no-require-imports': 'error',
13 | '@typescript-eslint/no-non-null-assertion': 'off',
14 | '@typescript-eslint/no-explicit-any': 'off',
15 | '@typescript-eslint/no-empty-function': 'off',
16 | '@typescript-eslint/ban-ts-comment': [
17 | 'error',
18 | {
19 | 'ts-ignore': 'allow-with-description'
20 | }
21 | ],
22 | 'no-console': 'error',
23 | 'yoda': 'error',
24 | 'prefer-const': [
25 | 'error',
26 | {
27 | destructuring: 'all'
28 | }
29 | ],
30 | 'no-control-regex': 'off',
31 | 'no-constant-condition': ['error', {checkLoops: false}],
32 | 'node/no-extraneous-import': 'error'
33 | },
34 | overrides: [
35 | {
36 | files: ['**/*{test,spec}.ts'],
37 | rules: {
38 | '@typescript-eslint/no-unused-vars': 'off',
39 | 'jest/no-standalone-expect': 'off',
40 | 'jest/no-conditional-expect': 'off',
41 | 'no-console': 'off',
42 |
43 | }
44 | }
45 | ],
46 | env: {
47 | node: true,
48 | es6: true,
49 | 'jest/globals': true
50 | }
51 | };
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | dist/** -diff linguist-generated=true
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @guerinoni
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | Hello!
4 |
5 | Thank you for your interest in contributing to this repository!
6 |
7 | We accept pull requests for bug fixes and features where we've discussed the approach in an issue and given the go-ahead for a community member to work on it. We'd also love to hear about ideas for new features as issues.
8 |
9 | Please **do**:
10 |
11 | - Check existing issues to verify that the [`bug`][bug issues] or [`feature request`][feature request issues] has not already been submitted.
12 | - Open an issue if things aren't working as expected.
13 | - Open an issue to propose a significant change.
14 | - Open a pull request to fix a bug.
15 | - Open a pull request to fix documentation about a command.
16 | - Open a pull request for any issue labelled [`help wanted`][hw] or [`good first issue`][gfi].
17 |
18 | Please **avoid**:
19 |
20 | - Opening pull requests for issues marked [`needs-design`][needs design], [`needs-investigation`][needs investigation], or [`blocked`][blocked].
21 | - Opening pull requests for any issue marked [`core`][core].
22 | - These issues require additional context from the core CLI team and any external pull requests will not be accepted.
23 |
24 | ## Building the listendev/action
25 |
26 | Prerequisites:
27 |
28 | - Node.js 16.x
29 |
30 | Build with:
31 |
32 | ```bash
33 | npm i
34 | npm run make
35 | ```
36 |
37 | ## Testing the listendev/action
38 |
39 | Run tests with: `npm run test`
40 |
41 | ## Commit convention
42 |
43 | We enforce the commits to follow the [Conventional Commits v1.0 spec](https://www.conventionalcommits.org/en/v1.0.0/) with the following (the default one) set of prefixes:
44 |
45 |
46 | - build
47 | - you're changing something in the build system
48 | - ci
49 | - you're taking care of our CI and automation
50 | - chore
51 | - little changes like typos; generally nothing very significant
52 | - docs
53 | - you are helping us with documentation
54 | - feat
55 | - your changes implement a new feature or update an existing one
56 | - fix
57 | - we'll always be grateful to you for your bug fixes
58 | - perf
59 | - you wrote a beautiful Go benchmark
60 | - refactor
61 | - when you are moving pieces around, changing file names, etc.
62 | - revert
63 | - you're reverting some changes: it may happen
64 | - test
65 | - your changes introduce, extend, or update some tests
66 |
67 |
68 | Let us now provide you some examples of commit messages we accept:
69 |
70 | ```
71 | chore: make linter happy
72 | chore: fix a little typo
73 | test: check edge case X doesn't happen
74 | fix: ensure edge case X doesn't verify anymore
75 | test: ensure lstn installation works correctly on windows runners
76 | docs: improve the commit convention examples
77 | build: make everything
78 | feat!: change the parameter X
79 | ```
80 |
81 | Notice that by using `!` after the prefix and before the colon you are communicating **breaking changes**.
82 |
83 | Enforcing the commits to follow this convention helps us:
84 |
85 | - keep the commit history readable
86 | - have an easily understandable commit history
87 | - manually label the pull requests accordingly
88 |
89 | Thank you for sticking to using it!
90 |
91 | Notice that we check the commit messages and lint them on every pull request. Should you find some bugs with the commit linting process, you can notify the author of the underlying parser at [leodido/go-conventionalcommits](https://github.com/leodido/go-conventionalcommits).
92 |
93 | Notice also that the enforcement of the Conventional Commit v1.0 spec is from v0.1.0 onwards, previous git history may not follow it perfectly.
94 |
95 | ## Submitting a pull request
96 |
97 | We also enforce the **pull requests titles** to follow the [Conventional Commits v1.0 spec](https://www.conventionalcommits.org/en/v1.0.0/).
98 |
99 | This because we have machinery in place that automatically labels the pull requests depending on the:
100 |
101 | - the path and file changes
102 | - the title of the pull request
103 | - the branch name of the pull request
104 |
105 | You can see the rules we use [here](../reviewpad.yml).
106 |
107 | It helps us automatically generate a wonderful changelog!
108 |
109 | Let's say that you spot a bug and you wanna fix it...
110 | You can open a pull request with title `fix: some subtle bug` and it will be automatically labeled with the `bug` label.
111 |
112 | 1. Create a new branch: `git checkout -b fix/some-subtle-bug`
113 | 1. Make your change, add tests, and ensure tests pass
114 | 1. Submit a pull request: `gh pr create --web`
115 |
116 | Please write **small pull requests** to ease our review and maintenance burdens.
117 |
118 | Contributions to this project are [released][legal] to the public under the [project's open source license][license].
119 |
120 | Please note that this project adheres to a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.
121 |
122 | ## Releases
123 |
124 | Just create a tag.
125 |
126 | ```
127 | git tag -a vX.Y.Z -m "Release vX.Y.Z"
128 | git push origin vX.Y.Z
129 | ```
130 |
131 | Once the release CI workflow completed, **manually** edit the release to:
132 |
133 | 1. generate GitHub release notes by clicking the top-right button
134 | 2. publish the new release on the GitHub Actions Marketplace by ensuring its checkbox is selected
135 |
136 | ## Resources
137 |
138 | - [How to Contribute to Open Source][]
139 | - [Using Pull Requests][]
140 | - [GitHub Help][]
141 |
142 | [bug issues]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3Abug
143 | [feature request issues]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement
144 | [hw]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3A"help+wanted"
145 | [blocked]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3Ablocked
146 | [needs design]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3A"needs+design"
147 | [needs investigation]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3A"needs+investigation"
148 | [gfi]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3A"good+first+issue"
149 | [core]: https://github.com/listendev/action/issues?q=is%3Aopen+is%3Aissue+label%3Acore
150 | [legal]: https://docs.github.com/en/free-pro-team@latest/github/site-policy/github-terms-of-service#6-contributions-under-repository-license
151 | [license]: ../LICENSE
152 | [code-of-conduct]: https://github.com/listendev/.github/blob/main/CODE_OF_CONDUCT.md
153 | [how to contribute to open source]: https://opensource.guide/how-to-contribute/
154 | [using pull requests]: https://docs.github.com/en/free-pro-team@latest/github/collaborating-with-issues-and-pull-requests/about-pull-requests
155 | [github help]: https://docs.github.com/
156 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41B Bug report"
3 | about: Report a bug or unexpected behavior while using this GitHub action
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### Describe the bug
11 |
12 | A clear and concise description of what the bug is.
13 |
14 | Please include a reference to the GitHub action workflow where you are using it.
15 |
16 | ### Expected vs actual behavior
17 |
18 | A clear and concise description of what you expected to happen and what actually happened.
19 |
20 | ### Logs
21 |
22 | Paste the activity from your command line. **REDACT IF NEEDED**.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Ask a question on how to use listendev/action
4 | about: For general-purpose questions and answers, see the discussions section.
5 | url: https://github.com/listendev/action/discussions
6 | - name: Ask a question about listen.dev
7 | about: Please check out our Discord for discussions about listen.dev and our approach to supply chain security.
8 | url: https://discord.gg/JB6tvTs5Fc
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feedback.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F4E3 Feedback"
3 | about: Give us general feedback about this GitHub action
4 | title: ""
5 | labels: feedback
6 | assignees: ""
7 | ---
8 |
9 | # Feedback
10 |
11 | You can use this template to give us structured feedback or just wipe it and leave us a note. Thank you!
12 |
13 | ## What have you loved?
14 |
15 | _eg., "the nice colors"_
16 |
17 | ## What was confusing or gave you pause?
18 |
19 | _eg., "it did something unexpected"_
20 |
21 | ## Are there features you'd like to see added?
22 |
23 | _eg., "erborist needs more unicorns"_
24 |
25 | ## Anything else?
26 |
27 | _eg., "have a nice day"_
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/submit_a_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "⭐ Submit a request"
3 | about: Surface a feature or problem that you think we should solve
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### Describe the feature or problem you’d like to solve
11 |
12 | A clear and concise description of what the feature or problem is.
13 |
14 | ### Proposed solution
15 |
16 | How will it benefit the project and its users?
17 |
18 | ### Additional context
19 |
20 | Add any other context like screenshots or mockups are helpful, if applicable.
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
9 |
10 | - [ ] I have read the [contributing guidelines](https://github.com/listendev/action/blob/main/.github/CONTRIBUTING.md)
11 | - [ ] I have written unit tests
12 | - [ ] I have made sure that the pull request is of reasonable size and can be easily reviewed
13 |
--------------------------------------------------------------------------------
/.github/codeql-config.yml:
--------------------------------------------------------------------------------
1 | paths-ignore:
2 | - 'dist/**'
3 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: codeql
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 | schedule:
9 | - cron: '0 8 * * 1' # every Monday at 8am
10 |
11 | jobs:
12 | call-codeql-analysis:
13 | name: analysis
14 | uses: actions/reusable-workflows/.github/workflows/codeql-analysis.yml@main
15 | with:
16 | codeql-cfg-path: './.github/codeql-config.yml'
17 |
--------------------------------------------------------------------------------
/.github/workflows/development.yml:
--------------------------------------------------------------------------------
1 | name: listendev
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths-ignore:
8 | - '**.md'
9 | pull_request:
10 | paths-ignore:
11 | - '**.md'
12 |
13 | jobs:
14 | development:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Checkout
18 | uses: actions/checkout@v4
19 |
20 | # Self inspect ourselves
21 | - uses: ./
22 | with:
23 | runtime: only
24 | jwt: ${{ secrets.LISTENDEV_TOKEN }}
25 |
26 | - name: Self inspect with nightly (private) CLI
27 | uses: ./
28 | with:
29 | runtime: only
30 | jwt: ${{ secrets.LISTENDEV_TOKEN }}
31 | lstn: dev
32 | env:
33 | pat_pvt_repo: ${{ secrets.PAT_PVT_REPO }}
34 |
35 | - name: Debug
36 | run: |
37 | sudo cat /var/run/jibril/default
38 |
39 | - name: Setup Node.JS
40 | uses: actions/setup-node@v4
41 | with:
42 | node-version: 20
43 |
44 | - name: Install dependencies
45 | run: npm ci
46 |
47 | - name: Run prettier
48 | run: npm run format-check
49 |
50 | - name: Run linter
51 | run: npm run lint
52 |
53 | - name: Build
54 | run: npm run build
55 |
56 | - name: Test
57 | run: npm test
58 |
--------------------------------------------------------------------------------
/.github/workflows/distribution.yml:
--------------------------------------------------------------------------------
1 | name: distribution
2 |
3 | # This workflow ensures that the generated contents of the dist directory match what they are expected to be.
4 | # For actions that follow our TypeScript or JavaScript templates, dist contains the packaged script that is executed by the runner.
5 | # Whenever you update the source code, the dist files must be regenerated for the changes to take effect.
6 |
7 | on:
8 | push:
9 | branches:
10 | - main
11 | paths-ignore:
12 | - '**.md'
13 | pull_request:
14 | paths-ignore:
15 | - '**.md'
16 | workflow_dispatch:
17 |
18 | jobs:
19 | distribution:
20 | uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
21 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: release
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | tags:
8 | - 'v*.*.*'
9 | pull_request:
10 | types:
11 | - labeled
12 |
13 | jobs:
14 | release:
15 | if: "${{ github.event.action != 'labeled' }}"
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v4
19 |
20 | # Bump the version on merging pull requests with specific labels (bump:major, bump:minor, bump:patch)
21 | - id: bumpr
22 | if: "${{ !startsWith(github.ref, 'refs/tags/') }}"
23 | uses: haya14busa/action-bumpr@v1
24 |
25 | # Update corresponding major and minor tags
26 | # e.g. update v1 and v1.2 when releasing v1.2.3
27 | - uses: haya14busa/action-update-semver@v1
28 | if: '${{ !steps.bumpr.outputs.skip }}'
29 | with:
30 | tag: ${{ steps.bumpr.outputs.next_version }}
31 |
32 | # Get the tag name
33 | - id: tag
34 | uses: haya14busa/action-cond@v1
35 | with:
36 | cond: "${{ startsWith(github.ref, 'refs/tags/') }}"
37 | if_true: ${{ github.ref }}
38 | if_false: ${{ steps.bumpr.outputs.next_version }}
39 |
40 | # Release
41 | - uses: actions/create-release@v1
42 | if: "${{ steps.tag.outputs.value != '' }}"
43 | env:
44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45 | with:
46 | tag_name: ${{ steps.tag.outputs.value }}
47 | release_name: Release ${{ steps.tag.outputs.value }}
48 | body: ${{ steps.bumpr.outputs.message }}
49 | draft: false
50 | prerelease: false
51 |
52 | release-check:
53 | name: 'release / check'
54 | if: ${{ github.event.action == 'labeled' }}
55 | runs-on: ubuntu-latest
56 | steps:
57 | - uses: actions/checkout@v4
58 | - name: Post bumpr status comment
59 | uses: haya14busa/action-bumpr@v1
60 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | name: testing
2 |
3 | on:
4 | pull_request:
5 | branches: ['main']
6 | push:
7 | branches: ['main']
8 |
9 | jobs:
10 | unit:
11 | strategy:
12 | fail-fast: false
13 | matrix:
14 | platform: [ubuntu-latest, macos-latest]
15 | runs-on: ${{ matrix.platform }}
16 | steps:
17 | - name: Check out
18 | uses: actions/checkout@v4
19 |
20 | - name: Install the dependencies
21 | run: npm ci
22 |
23 | - name: Run tests
24 | run: npm run test
25 |
26 | # TODO: check all the outputs
27 | integration:
28 | needs: unit
29 | strategy:
30 | fail-fast: false
31 | matrix:
32 | platform: [ubuntu-latest, macos-latest]
33 | runs-on: ${{ matrix.platform }}
34 | steps:
35 | - name: Check out
36 | uses: actions/checkout@v4
37 |
38 | - name: Debug options
39 | uses: ./
40 | with:
41 | lstn: v0.13.0
42 | lstn_flags: '--debug-options'
43 |
44 | - name: Debug jwt input
45 | uses: ./
46 | with:
47 | jwt: 'xxx.yyy.zzz' # NOTE: do not do this, use a secret
48 | lstn_flags: '--debug-options'
49 |
50 | - name: Debug jwt input with additional reporter
51 | uses: ./
52 | with:
53 | jwt: 'xxx.yyy.zzz' # NOTE: do not do this, use a secret
54 | lstn_flags: '-r gh-pull-comment --debug-options'
55 |
56 | - name: Debug invoking lstn from root with custom config file containing multiple lockfiles
57 | uses: ./
58 | with:
59 | jwt: 'xxx.123.987' # NOTE: do not do this, use a secret
60 | workdir: '.'
61 | lstn_flags: '--config __tests__/testdata/from_root.yaml --debug-options'
62 | # Expects "lockfiles": ["__tests__/testdata/monorepo/package-lock.json","__tests__/testdata/monorepo/poetry.lock","__tests__/testdata/monorepo/sub/poetry.lock"]
63 |
64 | - name: Debug invoking lstn from root with custom config file containing multiple lockfiles using action input
65 | uses: ./
66 | with:
67 | jwt: 'xxx.123.987' # NOTE: do not do this, use a secret
68 | workdir: '.'
69 | config: '__tests__/testdata/from_root.yaml'
70 | lstn_flags: '--debug-options'
71 | # Expects "lockfiles": ["__tests__/testdata/monorepo/package-lock.json","__tests__/testdata/monorepo/poetry.lock","__tests__/testdata/monorepo/sub/poetry.lock"]
72 |
73 | - name: Debug invoking lstn from root with custom config directory containing .lstn.yaml using action input
74 | uses: ./
75 | with:
76 | jwt: 'xxx.123.456' # NOTE: do not do this, use a secret
77 | workdir: '.'
78 | config: '__tests__/testdata'
79 | lstn_flags: '--debug-options'
80 | # Expects "lockfiles": ["monorepo/package-lock.json","monorepo/poetry.lock","monorepo/sub/poetry.lock"]
81 |
82 | - name: Debug invoking lstn from root with custom workdir + explicit lockfiles flag
83 | uses: ./
84 | with:
85 | jwt: 'xxx.123.789' # NOTE: do not do this, use a secret
86 | workdir: '__tests__/testdata'
87 | lstn_flags: '--lockfiles monorepo/package-lock.json,monorepo/sub/poetry.lock --debug-options'
88 | # Expects "lockfiles": ["monorepo/package-lock.json","monorepo/sub/poetry.lock"]
89 |
90 | - name: Debug invoking lstn from root with custom workdir containing .lstn.yaml (lockfiles relative to workdir)
91 | uses: ./
92 | with:
93 | jwt: 'xxx.123.789' # NOTE: do not do this, use a secret
94 | workdir: '__tests__/testdata'
95 | lstn_flags: '--debug-options'
96 | # Expects "lockfiles": ["monorepo/package-lock.json","monorepo/poetry.lock","monorepo/sub/poetry.lock"]
97 |
98 | - name: Debug invoking lstn from root with custom workdir containing default lockfiles
99 | uses: ./
100 | with:
101 | jwt: 'xxx.123.yyy' # NOTE: do not do this, use a secret
102 | workdir: '__tests__/testdata/monorepo'
103 | lstn_flags: '--debug-options'
104 | # Expects "lockfiles": ["package-lock.json","poetry.lock"]
105 |
106 | - name: Debug invoking CI eavesdrop tool
107 | if: runner.os == 'Linux'
108 | uses: ./
109 | with:
110 | jwt: 'xxx.yyy.zzz' # NOTE: do not do this, use a secret
111 | runtime: true
112 | lstn_flags: '--debug-options'
113 |
114 | # We wanna point the action to a directory that DOES NOT contain any lock file
115 | - name: Debug invoking CI eavesdrop tool only
116 | if: runner.os == 'Linux'
117 | uses: ./
118 | with:
119 | jwt: 'xxx.yyy.zzz' # NOTE: do not do this, use a secret
120 | workdir: '__tests__/testdata/nolockfiles'
121 | runtime: only
122 | lstn_flags: '--debug-options'
123 |
124 | - name: Self run (custom reporter)
125 | uses: ./
126 | with:
127 | reporter: gh-pull-review
128 | lstn_flags: '--debug-options'
129 |
130 | - name: Self run with lstn_flags
131 | uses: ./
132 | with:
133 | reporter: gh-pull-check
134 | lstn_flags: "--json --jq '.[] | select(.verdicts == [])' --debug-options"
135 |
--------------------------------------------------------------------------------
/.github/workflows/validation.yml:
--------------------------------------------------------------------------------
1 | name: validation
2 |
3 | # This workflow compiles and tests the code in the repo. It also checks that it passes linting and formatting rules.
4 | # Optionally, it can run npm audit on the packages in the repo.
5 |
6 | on:
7 | push:
8 | branches:
9 | - main
10 | paths-ignore:
11 | - '**.md'
12 | pull_request:
13 | paths-ignore:
14 | - '**.md'
15 |
16 | jobs:
17 | basic:
18 | uses: actions/reusable-workflows/.github/workflows/basic-validation.yml@main
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lib/
2 |
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 | lerna-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
13 |
14 | # Runtime data
15 | pids
16 | *.pid
17 | *.seed
18 | *.pid.lock
19 |
20 | # Directory for instrumented libs generated by jscoverage/JSCover
21 | lib-cov
22 |
23 | # Coverage directory used by tools like istanbul
24 | coverage
25 | *.lcov
26 |
27 | # nyc test coverage
28 | .nyc_output
29 |
30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
31 | .grunt
32 |
33 | # Bower dependency directory (https://bower.io/)
34 | bower_components
35 |
36 | # node-waf configuration
37 | .lock-wscript
38 |
39 | # Compiled binary addons (https://nodejs.org/api/addons.html)
40 | build/Release
41 |
42 | # Dependency directories
43 | node_modules/
44 | jspm_packages/
45 |
46 | # TypeScript v1 declaration files
47 | typings/
48 |
49 | # TypeScript cache
50 | *.tsbuildinfo
51 |
52 | # Optional npm cache directory
53 | .npm
54 |
55 | # Optional eslint cache
56 | .eslintcache
57 |
58 | # Microbundle cache
59 | .rpt2_cache/
60 | .rts2_cache_cjs/
61 | .rts2_cache_es/
62 | .rts2_cache_umd/
63 |
64 | # Optional REPL history
65 | .node_repl_history
66 |
67 | # Output of 'npm pack'
68 | *.tgz
69 |
70 | # Yarn Integrity file
71 | .yarn-integrity
72 |
73 | # dotenv environment variables file
74 | .env
75 | .env.test
76 |
77 | # parcel-bundler cache (https://parceljs.org/)
78 | .cache
79 |
80 | # Next.js build output
81 | .next
82 |
83 | # Nuxt.js build / generate output
84 | .nuxt
85 |
86 | # Gatsby files
87 | .cache/
88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
89 | # https://nextjs.org/blog/next-9-1#public-directory-support
90 | # public
91 |
92 | # vuepress build output
93 | .vuepress/dist
94 |
95 | # Serverless directories
96 | .serverless/
97 |
98 | # FuseBox cache
99 | .fusebox/
100 |
101 | # DynamoDB Local files
102 | .dynamodb/
103 |
104 | # TernJS port file
105 | .tern-port
106 |
107 | lstn
108 | .envrc
109 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Ignore list
2 | /*
3 |
4 | # Do not ignore these folders:
5 | !__tests__/
6 | !.github/
7 | !src/
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | // This is a reusable configuration file copied from https://github.com/actions/reusable-workflows/tree/main/reusable-configurations. Please don't make changes to this file as it's the subject of an automatic update.
2 | module.exports = {
3 | printWidth: 80,
4 | tabWidth: 2,
5 | useTabs: false,
6 | semi: true,
7 | singleQuote: true,
8 | trailingComma: 'none',
9 | bracketSpacing: false,
10 | arrowParens: 'avoid'
11 | };
12 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Farrukh Jadoon (https://github.com/jadoonf)
2 | Federico Guerinoni (https://github.com/guerinoni)
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # listendev/action
2 |
3 | > Proactive Security Monitoring Inside GitHub Actions 🐬
4 |
5 | _Observe network, file, and process behaviors during every workflow run and flags anomalous and malicious activities — such as connections to unknown IPs or unauthorized source code changes – in your GitHub actions workflows._
6 |
7 | ## Usage
8 |
9 | See [action.yml](action.yml).
10 |
11 | ### Basic
12 |
13 | ```yaml
14 | steps:
15 | - uses: listendev/action@v0.19.0
16 | with:
17 | runtime: only
18 | jwt: ${{ secrets.LSTN_API_KEY }}
19 | ```
20 |
21 | ### Full
22 |
23 | ```yaml
24 | steps:
25 | - uses: listendev/action@v0.19.0
26 | with:
27 | # The Github API token.
28 | # Defaults to ${{ github.token }}
29 | token: "..."
30 | # The listen.dev JWT token.
31 | # Defaults to empty string.
32 | jwt: ${{ secrets.MY_JWT_TOKEN }}
33 | # Whether to enable the eavesdrop tool or not to inspect the runtime threats in your CI.
34 | # Works only on linux runners. Requires a valid `jwt` option.
35 | # Defaults to false.
36 | runtime: "true|false|only"
37 | # The lstn version.
38 | # Defaults to the latest lstn release tag (recommended).
39 | lstn: "vX.Y.Z"
40 | # The working directory relative to the root one.
41 | # Defaults to the root directory.
42 | workdir: "."
43 | # The path to the YAML configuration file.
44 | # Or the path of the directory containing a .lstn.yaml file.
45 | # Defaults to empty.
46 | config: "..."
47 | # One or more reporting mechanisms (gh-pull-comment,gh-pull-review,gh-pull-check,pro)
48 | # Defaults to "gh-pull-comment" when there is no JWT input, to "pro" otherwise.
49 | reporter: "gh-pull-comment"
50 | # Addition lstn flags for power users
51 | lstn_flags: ""
52 | ```
53 |
54 | ### Connect to listen.dev
55 |
56 | Just [create a secret](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions) and pass it to the `jwt` input...
57 |
58 | ```yaml
59 | steps:
60 | - uses: listendev/action@v0.19.0
61 | with:
62 | runtime: true
63 | jwt: ${{ secrets.LSTN_API_KEY }}
64 | ```
65 |
66 | When the action notices that the [listen.dev](https://listen.dev) JWT secret exists, it will automatically override the reporter to the `pro` one.
67 |
68 | Because of the `runtime` option set to `true`, it will also start the CI eavesdrop tool under the hoods.
69 |
70 | Notice it only works on linux runners.
71 |
72 | **Where to get your JWT token?**
73 |
74 | [How to get your API key from the project settings](https://docs.listen.dev/workflows/generate-api-token).
75 |
76 | It's _recommended_ to regenerate the JWT token for every release, until we will release stable versions.
77 |
78 |
79 | Do you also want to also use another reporter together with the pro one?
80 |
81 | ```yaml
82 | steps:
83 | - uses: listendev/action@v0.19.0
84 | with:
85 | jwt: ${{ secrets.LSTN_API_KEY }}
86 | lstn_flags: "--reporter gh-pull-comment"
87 | ```
88 |
89 |
90 | ### Examples
91 |
92 | Let's say you don't want verdicts and events about the dependencies into your lockfiles.
93 | Or maybe your repository doesn't contain lockfiles (package-lock.json, poetry.lock, etc.) at all...
94 |
95 | So, you only want it to eavesdrop for runtime threats...
96 |
97 | ```yaml
98 | steps:
99 | - uses: listendev/action@v0.19.0
100 | with:
101 | runtime: only
102 | jwt: ${{ secrets.LSTN_API_KEY }}
103 | ```
104 |
105 | Let's say you want the verdicts in JSON format...
106 |
107 | ```yaml
108 | steps:
109 | - uses: listendev/action@v0.19.0
110 | with:
111 | lstn_flags: "--json"
112 | ```
113 |
114 | Let's say you only care for high severity verdicts...
115 |
116 | ```yaml
117 | steps:
118 | - uses: listendev/action@v0.19.0
119 | with:
120 | lstn: "v0.20.0"
121 | lstn_flags: "--select '@.severity == \"high\"'"
122 | ```
123 |
124 | You can select the verdicts also with the `select` input.
125 |
126 | Let's say we only care for dynamic instrumentation verdicts regarding processes...
127 |
128 | ```yaml
129 | steps:
130 | - uses: listendev/action@v0.19.0
131 | with:
132 | select: "(@.file =~ \"^dynamic\" && \"process\" in @.categories)"
133 | ```
134 |
135 | ## Development
136 |
137 | To develop this GitHub action you first need to install its dependencies:
138 |
139 | ```bash
140 | npm install
141 | ```
142 |
143 | You can then use `npm run build` to compile it. Also, remember that we check on every pull request that you've run this command, as to avoid the `dist/` directory to be out of sync.
144 |
145 | You can also run unit tests locally with the `npm run test` command.
146 |
147 | The CI makes extensive use of the official [GitHub reusable workflows](https://github.com/actions/reusable-workflows) for developing actions following best practices (see the [.github](./.github) directory).
148 |
149 | ## License
150 |
151 | The scripts and documentation in this project are released under the [Apache 2.0](LICENSE) license.
152 |
153 | ## Contributions
154 |
155 | Contributions are always welcome!
156 |
157 | See [contributor's guide](.github/CONTRIBUTING.md).
158 |
159 | ### Code of Conduct
160 |
161 | Practice kindness. ✨
162 |
163 | See [our code of conduct](https://github.com/listendev/.github/blob/main/CODE_OF_CONDUCT.md).
164 |
--------------------------------------------------------------------------------
/__tests__/.gitignore:
--------------------------------------------------------------------------------
1 | _temp
--------------------------------------------------------------------------------
/__tests__/flags.test.ts:
--------------------------------------------------------------------------------
1 | import * as flags from '../src/flags';
2 |
3 | describe('flags', () => {
4 | it('empty', () => {
5 | const input = '';
6 | expect(flags.parse(input)).toEqual([]);
7 | });
8 |
9 | it('parses singe bool flag', () => {
10 | const input = '--debug-options';
11 | expect(flags.parse(input)).toEqual(['--debug-options']);
12 | });
13 |
14 | it('parses multiple flags', () => {
15 | const input =
16 | '--debug-options -r gh-pull-check,gh-pull-comment --gh-pull-id 123';
17 | expect(flags.parse(input)).toEqual([
18 | '--debug-options',
19 | '-r',
20 | 'gh-pull-check,gh-pull-comment',
21 | '--gh-pull-id',
22 | '123'
23 | ]);
24 | });
25 |
26 | it('parses multiple flags with double quotes', () => {
27 | const input =
28 | '--debug-options -r "gh-pull-check, gh-pull-comment" --gh-pull-id 123';
29 | expect(flags.parse(input)).toEqual([
30 | '--debug-options',
31 | '-r',
32 | 'gh-pull-check, gh-pull-comment',
33 | '--gh-pull-id',
34 | '123'
35 | ]);
36 | });
37 |
38 | it('parses multiple flags with single quotes', () => {
39 | const input = "--debug-options --npm-registry 'https://registry.npmjs.org'";
40 | expect(flags.parse(input)).toEqual([
41 | '--debug-options',
42 | '--npm-registry',
43 | 'https://registry.npmjs.org'
44 | ]);
45 | });
46 |
47 | it('parses flag with nested quotes', () => {
48 | const input = '--select \'(@.severity == "high")\'';
49 | expect(flags.parse(input)).toEqual(['--select', '(@.severity == "high")']);
50 | });
51 |
52 | it('parses short flag (value with quotes)', () => {
53 | const input = '-s \'(@.severity == "high")\'';
54 | expect(flags.parse(input)).toEqual(['-s', '(@.severity == "high")']);
55 | });
56 |
57 | it('parses short flag with equal', () => {
58 | const input = `-s='@.severity == "high"'`;
59 | expect(flags.parse(input)).toEqual(['-s', `@.severity == "high"`]);
60 | });
61 |
62 | it('parses short flag', () => {
63 | const input = '-r=gh-pull-check,gh-pull-comment';
64 | expect(flags.parse(input)).toEqual(['-r', 'gh-pull-check,gh-pull-comment']);
65 | });
66 |
67 | it('parses flag with equal and nested quotes', () => {
68 | const input = `--select='"network" in @.categories' --json`;
69 | expect(flags.parse(input)).toEqual([
70 | '--select',
71 | `"network" in @.categories`,
72 | '--json'
73 | ]);
74 | });
75 |
76 | it('complex', () => {
77 | const input =
78 | '--select \'(@.file =~ "^dynamic" && "process" in @.categories)\' --json -r=gh-pull-check,gh-pull-comment --gh-pull-id 123';
79 | expect(flags.parse(input)).toEqual([
80 | '--select',
81 | '(@.file =~ "^dynamic" && "process" in @.categories)',
82 | '--json',
83 | '-r',
84 | 'gh-pull-check,gh-pull-comment',
85 | '--gh-pull-id',
86 | '123'
87 | ]);
88 | });
89 | });
90 |
--------------------------------------------------------------------------------
/__tests__/install.test._ts:
--------------------------------------------------------------------------------
1 | import {promises as fs} from 'fs';
2 | import * as path from 'path';
3 |
4 | const tmpdir = path.join(__dirname, '_temp');
5 | process.env['RUNNER_TEMP'] = tmpdir;
6 |
7 | import * as io from '@actions/io';
8 | import * as exec from '@actions/exec';
9 | import * as core from '@actions/core';
10 | import * as eavesdrop from '../src/eavesdrop';
11 | import * as lstn from '../src/lstn';
12 |
13 | jest.mock('../src/constants', () => ({
14 | EavesdropMustRun: true
15 | }));
16 |
17 | describe('installer', () => {
18 | beforeAll(async () => {
19 | await io.mkdirP(tmpdir);
20 | });
21 |
22 | afterAll(async () => {
23 | await io.rmRF(tmpdir);
24 | });
25 |
26 | it.skipWindows(
27 | 'installs specific lstn version',
28 | async () => {
29 | const getInputSpy = jest
30 | .spyOn(core, 'getInput')
31 | .mockImplementation((name: string) => {
32 | const data: {[key: string]: string} = {
33 | lstn: 'v0.3.1',
34 | workdir: '.',
35 | reporter: 'gh-pull-comment',
36 | lstn_flags: '',
37 | jwt: '12345'
38 | };
39 |
40 | return data[name];
41 | });
42 |
43 | const tool = new lstn.Tool();
44 |
45 | expect(getInputSpy).toHaveBeenCalledWith('lstn');
46 | expect(getInputSpy).toHaveBeenCalledWith('jwt', {required: true});
47 | expect(getInputSpy).toHaveBeenCalledWith('reporter');
48 | expect(getInputSpy).toHaveBeenCalledWith('select');
49 | expect(getInputSpy).toHaveBeenCalledWith('workdir');
50 | expect(getInputSpy).toHaveBeenCalledWith('lstn_flags');
51 |
52 | expect(tool.getVersion()).toEqual('v0.3.1');
53 |
54 | const dir = await fs.mkdtemp(path.join(tmpdir, 'lstn-'));
55 |
56 | const res = await tool.install(dir);
57 |
58 | expect(res.startsWith(dir)).toBe(true);
59 | expect(tool.isInstalled()).toBe(true);
60 |
61 | const out = await exec.getExecOutput(res, ['version']);
62 | expect(out.exitCode).toBe(0);
63 | expect(out.stderr.trim()).toEqual('lstn v0.3.1');
64 | },
65 | 5 * 60 * 1000
66 | );
67 |
68 | it.skipWindows(
69 | 'installs the latest version of lstn',
70 | async () => {
71 | const getInputSpy = jest
72 | .spyOn(core, 'getInput')
73 | .mockImplementation((name: string) => {
74 | const data: {[key: string]: string} = {
75 | lstn: 'latest',
76 | workdir: '.',
77 | reporter: 'gh-pull-comment',
78 | lstn_flags: '',
79 | jwt: '12345'
80 | };
81 |
82 | return data[name];
83 | });
84 |
85 | const tool = new lstn.Tool();
86 |
87 | expect(getInputSpy).toHaveBeenCalledWith('lstn');
88 | expect(getInputSpy).toHaveBeenCalledWith('jwt', {required: true});
89 | expect(getInputSpy).toHaveBeenCalledWith('reporter');
90 | expect(getInputSpy).toHaveBeenCalledWith('select');
91 | expect(getInputSpy).toHaveBeenCalledWith('workdir');
92 | expect(getInputSpy).toHaveBeenCalledWith('lstn_flags');
93 |
94 | expect(tool.getVersion()).toEqual(Object.keys(eavesdrop.Tool.tagMap)[0]);
95 |
96 | const dir = await fs.mkdtemp(path.join(tmpdir, 'lstn-'));
97 |
98 | const res = await tool.install(dir);
99 |
100 | expect(res.startsWith(dir)).toBe(true);
101 | expect(tool.isInstalled()).toBe(true);
102 |
103 | const code = await exec.exec(res, ['version']);
104 | expect(code).toBe(0);
105 | },
106 | 5 * 60 * 1000
107 | );
108 |
109 | it.onLinux(
110 | 'installs eavesdrop tool for the lstn v0.13.0',
111 | async () => {
112 | const getInputSpy = jest
113 | .spyOn(core, 'getInput')
114 | .mockImplementation((name: string) => {
115 | const data: {[key: string]: string} = {
116 | lstn: 'v0.13.0'
117 | };
118 |
119 | return data[name];
120 | });
121 |
122 | const tool = new eavesdrop.Tool();
123 |
124 | expect(getInputSpy).toHaveBeenCalledWith('lstn');
125 | expect(getInputSpy).toHaveBeenCalledWith('eavesdrop_version');
126 |
127 | expect(tool.getName()).toEqual('argus');
128 | expect(tool.getVersion()).toEqual('v0.1');
129 | expect(tool.getCliEnablingCommand()).toEqual(['ci']);
130 |
131 | const fileDir = await fs.mkdtemp(path.join(tmpdir, 'lstn-'));
132 | const destDir = await fs.mkdtemp(path.join(tmpdir, 'eavesdrop-'));
133 | const toolPath = await tool.install(fileDir, destDir);
134 |
135 | expect(tool.isInstalled()).toBe(true);
136 |
137 | const code = await exec.exec(toolPath, ['-v']);
138 | expect(code).toBe(0);
139 | },
140 | 5 * 60 * 1000
141 | );
142 |
143 | it.onLinux(
144 | 'installs eavesdrop tool for the latest lstn',
145 | async () => {
146 | const getInputSpy = jest
147 | .spyOn(core, 'getInput')
148 | .mockImplementation((name: string) => {
149 | const data: {[key: string]: string} = {
150 | lstn: 'latest'
151 | };
152 |
153 | return data[name];
154 | });
155 |
156 | const tool = new eavesdrop.Tool();
157 |
158 | expect(getInputSpy).toHaveBeenCalledWith('lstn');
159 | expect(getInputSpy).toHaveBeenCalledWith('eavesdrop_version');
160 |
161 | expect(tool.getVersion()).toEqual('v1.0');
162 | expect(tool.getCliEnablingCommand()).toEqual(['ci', 'enable']);
163 | expect(tool.getName()).toEqual('jibril');
164 |
165 | const fileDir = await fs.mkdtemp(path.join(tmpdir, 'lstn-'));
166 | const destDir = await fs.mkdtemp(path.join(tmpdir, 'eavesdrop-'));
167 | const toolPath = await tool.install(fileDir, destDir);
168 |
169 | expect(tool.isInstalled()).toBe(true);
170 |
171 | const code = await exec.exec(toolPath, ['--version']);
172 | expect(code).toBe(0);
173 | },
174 | 5 * 60 * 1000
175 | );
176 |
177 | it.onLinux(
178 | 'installs custom eavesdrop tool version lt v0.8',
179 | async () => {
180 | const getInputSpy = jest
181 | .spyOn(core, 'getInput')
182 | .mockImplementation((name: string) => {
183 | const data: {[key: string]: string} = {
184 | lstn: 'v0.15.0',
185 | eavesdrop_version: 'v0.3'
186 | };
187 |
188 | return data[name];
189 | });
190 |
191 | const tool = new eavesdrop.Tool();
192 |
193 | expect(getInputSpy).toHaveBeenCalledWith('lstn');
194 | expect(getInputSpy).toHaveBeenCalledWith('eavesdrop_version');
195 |
196 | expect(tool.getVersion()).toEqual('v0.3.0');
197 | expect(tool.getCliEnablingCommand()).toEqual(['ci']);
198 | expect(tool.getName()).toEqual('argus');
199 |
200 | const fileDir = await fs.mkdtemp(path.join(tmpdir, 'lstn-'));
201 | const destDir = await fs.mkdtemp(path.join(tmpdir, 'eavesdrop-'));
202 | const toolPath = await tool.install(fileDir, destDir);
203 |
204 | expect(tool.isInstalled()).toBe(true);
205 |
206 | const code = await exec.exec(toolPath, ['--version']);
207 | expect(code).toBe(0);
208 | },
209 | 5 * 60 * 1000
210 | );
211 |
212 | it.onLinux(
213 | 'installs nightly eavesdrop tool version with lstn gte v0.16.0',
214 | async () => {
215 | const getInputSpy = jest
216 | .spyOn(core, 'getInput')
217 | .mockImplementation((name: string) => {
218 | const data: {[key: string]: string} = {
219 | lstn: 'v0.16.0',
220 | eavesdrop_version: '0.0'
221 | };
222 |
223 | return data[name];
224 | });
225 |
226 | const tool = new eavesdrop.Tool();
227 |
228 | expect(getInputSpy).toHaveBeenCalledWith('lstn');
229 | expect(getInputSpy).toHaveBeenCalledWith('eavesdrop_version');
230 |
231 | expect(tool.getVersion()).toEqual('v0.0.0');
232 | expect(tool.getCliEnablingCommand()).toEqual(['ci', 'enable']);
233 | expect(tool.getName()).toEqual('jibril');
234 |
235 | const fileDir = await fs.mkdtemp(path.join(tmpdir, 'lstn-'));
236 | const destDir = await fs.mkdtemp(path.join(tmpdir, 'eavesdrop-'));
237 | const toolPath = await tool.install(fileDir, destDir);
238 |
239 | expect(tool.isInstalled()).toBe(true);
240 |
241 | const code = await exec.exec(toolPath, ['--version']);
242 | expect(code).toBe(0);
243 | },
244 | 5 * 60 * 1000
245 | );
246 |
247 | it.skipWindows(
248 | 'installs custom eavesdrop tool version lt v0.8 with lstn gte v0.16.0 should error',
249 | async () => {
250 | const getInputSpy = jest
251 | .spyOn(core, 'getInput')
252 | .mockImplementation((name: string) => {
253 | const data: {[key: string]: string} = {
254 | lstn: 'v0.16.0',
255 | eavesdrop_version: 'v0.3'
256 | };
257 |
258 | return data[name];
259 | });
260 |
261 | expect(() => new eavesdrop.Tool()).toThrow(
262 | 'custom eavesdrop tool version (v0.3) cannot work with lstn versions >= v0.16.0'
263 | );
264 | },
265 | 5 * 60 * 1000
266 | );
267 |
268 | it.skipWindows(
269 | 'installs custom eavesdrop tool version gte v0.8 with lstn lt v0.16.0 should error',
270 | async () => {
271 | const getInputSpy = jest
272 | .spyOn(core, 'getInput')
273 | .mockImplementation((name: string) => {
274 | const data: {[key: string]: string} = {
275 | lstn: 'v0.15.0',
276 | eavesdrop_version: 'v1.0'
277 | };
278 |
279 | return data[name];
280 | });
281 |
282 | expect(() => new eavesdrop.Tool()).toThrow(
283 | 'custom eavesdrop tool version (v1.0) cannot work with lstn versions < v0.16.0'
284 | );
285 | },
286 | 5 * 60 * 1000
287 | );
288 |
289 | it.skipWindows(
290 | 'installs nightly eavesdrop tool version with lstn lt v0.16.0 should error',
291 | async () => {
292 | const getInputSpy = jest
293 | .spyOn(core, 'getInput')
294 | .mockImplementation((name: string) => {
295 | const data: {[key: string]: string} = {
296 | lstn: 'v0.15.0',
297 | eavesdrop_version: 'v0.0'
298 | };
299 |
300 | return data[name];
301 | });
302 |
303 | expect(() => new eavesdrop.Tool()).toThrow(
304 | 'nightly eavesdrop tool version (v0.0) cannot work with lstn versions < v0.16.0'
305 | );
306 | },
307 | 5 * 60 * 1000
308 | );
309 |
310 | it.skipWindows(
311 | 'installs unsupported eavesdrop tool version throws',
312 | async () => {
313 | const getInputSpy = jest
314 | .spyOn(core, 'getInput')
315 | .mockImplementation((name: string) => {
316 | const data: {[key: string]: string} = {
317 | lstn: 'latest',
318 | eavesdrop_version: 'v0.2'
319 | };
320 |
321 | return data[name];
322 | });
323 |
324 | expect(() => new eavesdrop.Tool()).toThrow(
325 | `unsupported custom eavesdrop tool version (v0.2)`
326 | );
327 | },
328 | 5 * 60 * 1000
329 | );
330 | });
331 |
--------------------------------------------------------------------------------
/__tests__/testdata/.lstn.yaml:
--------------------------------------------------------------------------------
1 | timeout: 3000
2 | lockfiles:
3 | - monorepo/package-lock.json
4 | - monorepo/poetry.lock
5 | - monorepo/sub/poetry.lock
6 |
--------------------------------------------------------------------------------
/__tests__/testdata/from_root.yaml:
--------------------------------------------------------------------------------
1 | timeout: 5000
2 | lockfiles:
3 | - __tests__/testdata/monorepo/package-lock.json
4 | - __tests__/testdata/monorepo/poetry.lock
5 | - __tests__/testdata/monorepo/sub/poetry.lock
6 |
--------------------------------------------------------------------------------
/__tests__/testdata/monorepo/package-lock.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listendev/action/49b8e3dcdec362c3603fb4e79a366e7e30b8451d/__tests__/testdata/monorepo/package-lock.json
--------------------------------------------------------------------------------
/__tests__/testdata/monorepo/poetry.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listendev/action/49b8e3dcdec362c3603fb4e79a366e7e30b8451d/__tests__/testdata/monorepo/poetry.lock
--------------------------------------------------------------------------------
/__tests__/testdata/monorepo/sub/poetry.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listendev/action/49b8e3dcdec362c3603fb4e79a366e7e30b8451d/__tests__/testdata/monorepo/sub/poetry.lock
--------------------------------------------------------------------------------
/__tests__/testdata/nolockfiles/.gitignore:
--------------------------------------------------------------------------------
1 | !.gitignore
2 |
--------------------------------------------------------------------------------
/__tests__/utils.test.ts:
--------------------------------------------------------------------------------
1 | import * as utils from '../src/utils';
2 | import * as path from 'path';
3 |
4 | describe('checkPath', () => {
5 | const cwd = path.basename(__dirname);
6 |
7 | it('empty', async () => {
8 | const res = await utils.checkPath('');
9 | expect(res).toEqual({exists: false});
10 | });
11 |
12 | it('existing folder', async () => {
13 | const res = await utils.checkPath(path.join(cwd, 'testdata'));
14 |
15 | expect(res).toEqual({exists: true, isFile: false});
16 | });
17 |
18 | it('existing file', async () => {
19 | const res = await utils.checkPath(
20 | path.join(cwd, 'testdata', 'from_root.yaml')
21 | );
22 |
23 | expect(res).toEqual({exists: true, isFile: true});
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/action.yml:
--------------------------------------------------------------------------------
1 | name: "listen.dev"
2 | description: "Proactive Security Monitoring Inside GitHub Actions."
3 | author: "The listen.dev team "
4 | inputs:
5 | token:
6 | description: "The GitHub API token."
7 | required: true
8 | default: ${{ github.token }}
9 | jwt:
10 | description: "The listen.dev JWT token."
11 | required: false
12 | default: ""
13 | lstn:
14 | description: "The lstn CLI version."
15 | required: false
16 | default: "latest"
17 | runtime:
18 | description: "Whether to only or also use our eavesdrop tool to inspect the runtime threats in your CI. A listen.dev JWT token is mandatory."
19 | required: false
20 | default: "false"
21 | workdir:
22 | description: "Working directory relative to the root directory."
23 | required: false
24 | default: "."
25 | config:
26 | description: "The path of the configuration file."
27 | required: false
28 | default: ""
29 | reporter:
30 | description: "Preferred reporting mechanisms (gh-pull-comment,gh-pull-review,gh-pull-check,pro)"
31 | required: false
32 | default: "gh-pull-comment"
33 | select:
34 | description: "JSONPath script expression to filter the output verdicts"
35 | required: false
36 | default: ""
37 | lstn_flags:
38 | description: "Additional lstn CLI flags"
39 | required: false
40 | default: ""
41 | eavesdrop_version:
42 | description: "Use a custom version of our CI eavesdrop tool"
43 | required: false
44 | default: ""
45 |
46 | runs:
47 | using: "node20"
48 | main: "dist/index.js"
49 | post: "dist/index.js"
50 |
51 | # https://actions-cool.github.io/github-action-branding/
52 | branding:
53 | icon: 'shield'
54 | color: 'green'
55 |
--------------------------------------------------------------------------------
/devbox.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.6/.schema/devbox.schema.json",
3 | "packages": ["nodejs@20"],
4 | "shell": {
5 | "init_hook": [
6 | "echo 'Welcome to devbox!' > /dev/null"
7 | ],
8 | "scripts": {
9 | "test": [
10 | "echo \"Error: no test specified\" && exit 1"
11 | ]
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/devbox.lock:
--------------------------------------------------------------------------------
1 | {
2 | "lockfile_version": "1",
3 | "packages": {
4 | "github:NixOS/nixpkgs/nixpkgs-unstable": {
5 | "last_modified": "2025-05-04T04:25:16Z",
6 | "resolved": "github:NixOS/nixpkgs/6b1c028bce9c89e9824cde040d6986d428296055?lastModified=1746332716&narHash=sha256-VBmKSkmw9PYBCEGhBKzORjx%2BnwNZkPZyHcUHE21A%2Fws%3D"
7 | },
8 | "nodejs@20": {
9 | "last_modified": "2025-03-16T23:54:35Z",
10 | "plugin_version": "0.0.2",
11 | "resolved": "github:NixOS/nixpkgs/5d9b5431f967007b3952c057fc92af49a4c5f3b2#nodejs_20",
12 | "source": "devbox-search",
13 | "version": "20.19.0",
14 | "systems": {
15 | "aarch64-darwin": {
16 | "outputs": [
17 | {
18 | "name": "out",
19 | "path": "/nix/store/4i96rnl7hdzm3k3w36gx7d2p1af3b64q-nodejs-20.19.0",
20 | "default": true
21 | },
22 | {
23 | "name": "libv8",
24 | "path": "/nix/store/dvr6jyyhygpci5yj5mdl3p0xi2qcm02g-nodejs-20.19.0-libv8"
25 | }
26 | ],
27 | "store_path": "/nix/store/4i96rnl7hdzm3k3w36gx7d2p1af3b64q-nodejs-20.19.0"
28 | },
29 | "aarch64-linux": {
30 | "outputs": [
31 | {
32 | "name": "out",
33 | "path": "/nix/store/qz522zmsx441py29xy69sf5671bkhpj2-nodejs-20.19.0",
34 | "default": true
35 | },
36 | {
37 | "name": "libv8",
38 | "path": "/nix/store/7i02830b2pxlapzav6yyggymqmp6rk02-nodejs-20.19.0-libv8"
39 | }
40 | ],
41 | "store_path": "/nix/store/qz522zmsx441py29xy69sf5671bkhpj2-nodejs-20.19.0"
42 | },
43 | "x86_64-darwin": {
44 | "outputs": [
45 | {
46 | "name": "out",
47 | "path": "/nix/store/4k73p2z9h5rnfv9gal8n6m4srx5sggs8-nodejs-20.19.0",
48 | "default": true
49 | },
50 | {
51 | "name": "libv8",
52 | "path": "/nix/store/px89hqr3wcfk0w6146hf4171bvj4chgp-nodejs-20.19.0-libv8"
53 | }
54 | ],
55 | "store_path": "/nix/store/4k73p2z9h5rnfv9gal8n6m4srx5sggs8-nodejs-20.19.0"
56 | },
57 | "x86_64-linux": {
58 | "outputs": [
59 | {
60 | "name": "out",
61 | "path": "/nix/store/088a1y8kvrmvi7vm5ff67hg7c4hcnqg7-nodejs-20.19.0",
62 | "default": true
63 | },
64 | {
65 | "name": "libv8",
66 | "path": "/nix/store/njqqwr5311xmnm05ms3n7b8piwnyq7x1-nodejs-20.19.0-libv8"
67 | }
68 | ],
69 | "store_path": "/nix/store/088a1y8kvrmvi7vm5ff67hg7c4hcnqg7-nodejs-20.19.0"
70 | }
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/dist/licenses.txt:
--------------------------------------------------------------------------------
1 | @actions/core
2 | MIT
3 | The MIT License (MIT)
4 |
5 | Copyright 2019 GitHub
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | @actions/exec
14 | MIT
15 | The MIT License (MIT)
16 |
17 | Copyright 2019 GitHub
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
20 |
21 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 | @actions/http-client
26 | MIT
27 | Actions Http Client for Node.js
28 |
29 | Copyright (c) GitHub, Inc.
30 |
31 | All rights reserved.
32 |
33 | MIT License
34 |
35 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
36 | associated documentation files (the "Software"), to deal in the Software without restriction,
37 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
38 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
39 | subject to the following conditions:
40 |
41 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
42 |
43 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
44 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
45 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
46 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48 |
49 |
50 | @actions/io
51 | MIT
52 | The MIT License (MIT)
53 |
54 | Copyright 2019 GitHub
55 |
56 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
57 |
58 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
59 |
60 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61 |
62 | @actions/tool-cache
63 | MIT
64 | The MIT License (MIT)
65 |
66 | Copyright 2019 GitHub
67 |
68 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
69 |
70 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
71 |
72 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
73 |
74 | @fastify/busboy
75 | MIT
76 | Copyright Brian White. All rights reserved.
77 |
78 | Permission is hereby granted, free of charge, to any person obtaining a copy
79 | of this software and associated documentation files (the "Software"), to
80 | deal in the Software without restriction, including without limitation the
81 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
82 | sell copies of the Software, and to permit persons to whom the Software is
83 | furnished to do so, subject to the following conditions:
84 |
85 | The above copyright notice and this permission notice shall be included in
86 | all copies or substantial portions of the Software.
87 |
88 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
89 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
90 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
91 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
92 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
93 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
94 | IN THE SOFTWARE.
95 |
96 | @octokit/auth-token
97 | MIT
98 | The MIT License
99 |
100 | Copyright (c) 2019 Octokit contributors
101 |
102 | Permission is hereby granted, free of charge, to any person obtaining a copy
103 | of this software and associated documentation files (the "Software"), to deal
104 | in the Software without restriction, including without limitation the rights
105 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
106 | copies of the Software, and to permit persons to whom the Software is
107 | furnished to do so, subject to the following conditions:
108 |
109 | The above copyright notice and this permission notice shall be included in
110 | all copies or substantial portions of the Software.
111 |
112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
113 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
114 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
115 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
116 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
117 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
118 | THE SOFTWARE.
119 |
120 |
121 | @octokit/core
122 | MIT
123 | The MIT License
124 |
125 | Copyright (c) 2019 Octokit contributors
126 |
127 | Permission is hereby granted, free of charge, to any person obtaining a copy
128 | of this software and associated documentation files (the "Software"), to deal
129 | in the Software without restriction, including without limitation the rights
130 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
131 | copies of the Software, and to permit persons to whom the Software is
132 | furnished to do so, subject to the following conditions:
133 |
134 | The above copyright notice and this permission notice shall be included in
135 | all copies or substantial portions of the Software.
136 |
137 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
138 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
139 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
140 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
141 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
142 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
143 | THE SOFTWARE.
144 |
145 |
146 | @octokit/endpoint
147 | MIT
148 | The MIT License
149 |
150 | Copyright (c) 2018 Octokit contributors
151 |
152 | Permission is hereby granted, free of charge, to any person obtaining a copy
153 | of this software and associated documentation files (the "Software"), to deal
154 | in the Software without restriction, including without limitation the rights
155 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
156 | copies of the Software, and to permit persons to whom the Software is
157 | furnished to do so, subject to the following conditions:
158 |
159 | The above copyright notice and this permission notice shall be included in
160 | all copies or substantial portions of the Software.
161 |
162 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
163 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
165 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
166 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
167 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
168 | THE SOFTWARE.
169 |
170 |
171 | @octokit/graphql
172 | MIT
173 | The MIT License
174 |
175 | Copyright (c) 2018 Octokit contributors
176 |
177 | Permission is hereby granted, free of charge, to any person obtaining a copy
178 | of this software and associated documentation files (the "Software"), to deal
179 | in the Software without restriction, including without limitation the rights
180 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
181 | copies of the Software, and to permit persons to whom the Software is
182 | furnished to do so, subject to the following conditions:
183 |
184 | The above copyright notice and this permission notice shall be included in
185 | all copies or substantial portions of the Software.
186 |
187 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
189 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
190 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
192 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
193 | THE SOFTWARE.
194 |
195 |
196 | @octokit/plugin-paginate-rest
197 | MIT
198 | MIT License Copyright (c) 2019 Octokit contributors
199 |
200 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
201 |
202 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
203 |
204 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
205 |
206 |
207 | @octokit/plugin-request-log
208 | MIT
209 | MIT License Copyright (c) 2020 Octokit contributors
210 |
211 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
212 |
213 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
214 |
215 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
216 |
217 |
218 | @octokit/plugin-rest-endpoint-methods
219 | MIT
220 | MIT License Copyright (c) 2019 Octokit contributors
221 |
222 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
223 |
224 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
225 |
226 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
227 |
228 |
229 | @octokit/request
230 | MIT
231 | The MIT License
232 |
233 | Copyright (c) 2018 Octokit contributors
234 |
235 | Permission is hereby granted, free of charge, to any person obtaining a copy
236 | of this software and associated documentation files (the "Software"), to deal
237 | in the Software without restriction, including without limitation the rights
238 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
239 | copies of the Software, and to permit persons to whom the Software is
240 | furnished to do so, subject to the following conditions:
241 |
242 | The above copyright notice and this permission notice shall be included in
243 | all copies or substantial portions of the Software.
244 |
245 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
246 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
247 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
248 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
249 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
250 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
251 | THE SOFTWARE.
252 |
253 |
254 | @octokit/request-error
255 | MIT
256 | The MIT License
257 |
258 | Copyright (c) 2019 Octokit contributors
259 |
260 | Permission is hereby granted, free of charge, to any person obtaining a copy
261 | of this software and associated documentation files (the "Software"), to deal
262 | in the Software without restriction, including without limitation the rights
263 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
264 | copies of the Software, and to permit persons to whom the Software is
265 | furnished to do so, subject to the following conditions:
266 |
267 | The above copyright notice and this permission notice shall be included in
268 | all copies or substantial portions of the Software.
269 |
270 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
271 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
272 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
273 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
274 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
275 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
276 | THE SOFTWARE.
277 |
278 |
279 | @octokit/rest
280 | MIT
281 | The MIT License
282 |
283 | Copyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer)
284 | Copyright (c) 2017-2018 Octokit contributors
285 |
286 | Permission is hereby granted, free of charge, to any person obtaining a copy
287 | of this software and associated documentation files (the "Software"), to deal
288 | in the Software without restriction, including without limitation the rights
289 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
290 | copies of the Software, and to permit persons to whom the Software is
291 | furnished to do so, subject to the following conditions:
292 |
293 | The above copyright notice and this permission notice shall be included in
294 | all copies or substantial portions of the Software.
295 |
296 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
297 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
298 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
299 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
300 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
301 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
302 | THE SOFTWARE.
303 |
304 |
305 | asynckit
306 | MIT
307 | The MIT License (MIT)
308 |
309 | Copyright (c) 2016 Alex Indigo
310 |
311 | Permission is hereby granted, free of charge, to any person obtaining a copy
312 | of this software and associated documentation files (the "Software"), to deal
313 | in the Software without restriction, including without limitation the rights
314 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
315 | copies of the Software, and to permit persons to whom the Software is
316 | furnished to do so, subject to the following conditions:
317 |
318 | The above copyright notice and this permission notice shall be included in all
319 | copies or substantial portions of the Software.
320 |
321 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
322 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
323 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
324 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
325 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
326 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
327 | SOFTWARE.
328 |
329 |
330 | axios
331 | MIT
332 | # Copyright (c) 2014-present Matt Zabriskie & Collaborators
333 |
334 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
335 |
336 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
337 |
338 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
339 |
340 |
341 | before-after-hook
342 | Apache-2.0
343 | Apache License
344 | Version 2.0, January 2004
345 | http://www.apache.org/licenses/
346 |
347 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
348 |
349 | 1. Definitions.
350 |
351 | "License" shall mean the terms and conditions for use, reproduction,
352 | and distribution as defined by Sections 1 through 9 of this document.
353 |
354 | "Licensor" shall mean the copyright owner or entity authorized by
355 | the copyright owner that is granting the License.
356 |
357 | "Legal Entity" shall mean the union of the acting entity and all
358 | other entities that control, are controlled by, or are under common
359 | control with that entity. For the purposes of this definition,
360 | "control" means (i) the power, direct or indirect, to cause the
361 | direction or management of such entity, whether by contract or
362 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
363 | outstanding shares, or (iii) beneficial ownership of such entity.
364 |
365 | "You" (or "Your") shall mean an individual or Legal Entity
366 | exercising permissions granted by this License.
367 |
368 | "Source" form shall mean the preferred form for making modifications,
369 | including but not limited to software source code, documentation
370 | source, and configuration files.
371 |
372 | "Object" form shall mean any form resulting from mechanical
373 | transformation or translation of a Source form, including but
374 | not limited to compiled object code, generated documentation,
375 | and conversions to other media types.
376 |
377 | "Work" shall mean the work of authorship, whether in Source or
378 | Object form, made available under the License, as indicated by a
379 | copyright notice that is included in or attached to the work
380 | (an example is provided in the Appendix below).
381 |
382 | "Derivative Works" shall mean any work, whether in Source or Object
383 | form, that is based on (or derived from) the Work and for which the
384 | editorial revisions, annotations, elaborations, or other modifications
385 | represent, as a whole, an original work of authorship. For the purposes
386 | of this License, Derivative Works shall not include works that remain
387 | separable from, or merely link (or bind by name) to the interfaces of,
388 | the Work and Derivative Works thereof.
389 |
390 | "Contribution" shall mean any work of authorship, including
391 | the original version of the Work and any modifications or additions
392 | to that Work or Derivative Works thereof, that is intentionally
393 | submitted to Licensor for inclusion in the Work by the copyright owner
394 | or by an individual or Legal Entity authorized to submit on behalf of
395 | the copyright owner. For the purposes of this definition, "submitted"
396 | means any form of electronic, verbal, or written communication sent
397 | to the Licensor or its representatives, including but not limited to
398 | communication on electronic mailing lists, source code control systems,
399 | and issue tracking systems that are managed by, or on behalf of, the
400 | Licensor for the purpose of discussing and improving the Work, but
401 | excluding communication that is conspicuously marked or otherwise
402 | designated in writing by the copyright owner as "Not a Contribution."
403 |
404 | "Contributor" shall mean Licensor and any individual or Legal Entity
405 | on behalf of whom a Contribution has been received by Licensor and
406 | subsequently incorporated within the Work.
407 |
408 | 2. Grant of Copyright License. Subject to the terms and conditions of
409 | this License, each Contributor hereby grants to You a perpetual,
410 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
411 | copyright license to reproduce, prepare Derivative Works of,
412 | publicly display, publicly perform, sublicense, and distribute the
413 | Work and such Derivative Works in Source or Object form.
414 |
415 | 3. Grant of Patent License. Subject to the terms and conditions of
416 | this License, each Contributor hereby grants to You a perpetual,
417 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
418 | (except as stated in this section) patent license to make, have made,
419 | use, offer to sell, sell, import, and otherwise transfer the Work,
420 | where such license applies only to those patent claims licensable
421 | by such Contributor that are necessarily infringed by their
422 | Contribution(s) alone or by combination of their Contribution(s)
423 | with the Work to which such Contribution(s) was submitted. If You
424 | institute patent litigation against any entity (including a
425 | cross-claim or counterclaim in a lawsuit) alleging that the Work
426 | or a Contribution incorporated within the Work constitutes direct
427 | or contributory patent infringement, then any patent licenses
428 | granted to You under this License for that Work shall terminate
429 | as of the date such litigation is filed.
430 |
431 | 4. Redistribution. You may reproduce and distribute copies of the
432 | Work or Derivative Works thereof in any medium, with or without
433 | modifications, and in Source or Object form, provided that You
434 | meet the following conditions:
435 |
436 | (a) You must give any other recipients of the Work or
437 | Derivative Works a copy of this License; and
438 |
439 | (b) You must cause any modified files to carry prominent notices
440 | stating that You changed the files; and
441 |
442 | (c) You must retain, in the Source form of any Derivative Works
443 | that You distribute, all copyright, patent, trademark, and
444 | attribution notices from the Source form of the Work,
445 | excluding those notices that do not pertain to any part of
446 | the Derivative Works; and
447 |
448 | (d) If the Work includes a "NOTICE" text file as part of its
449 | distribution, then any Derivative Works that You distribute must
450 | include a readable copy of the attribution notices contained
451 | within such NOTICE file, excluding those notices that do not
452 | pertain to any part of the Derivative Works, in at least one
453 | of the following places: within a NOTICE text file distributed
454 | as part of the Derivative Works; within the Source form or
455 | documentation, if provided along with the Derivative Works; or,
456 | within a display generated by the Derivative Works, if and
457 | wherever such third-party notices normally appear. The contents
458 | of the NOTICE file are for informational purposes only and
459 | do not modify the License. You may add Your own attribution
460 | notices within Derivative Works that You distribute, alongside
461 | or as an addendum to the NOTICE text from the Work, provided
462 | that such additional attribution notices cannot be construed
463 | as modifying the License.
464 |
465 | You may add Your own copyright statement to Your modifications and
466 | may provide additional or different license terms and conditions
467 | for use, reproduction, or distribution of Your modifications, or
468 | for any such Derivative Works as a whole, provided Your use,
469 | reproduction, and distribution of the Work otherwise complies with
470 | the conditions stated in this License.
471 |
472 | 5. Submission of Contributions. Unless You explicitly state otherwise,
473 | any Contribution intentionally submitted for inclusion in the Work
474 | by You to the Licensor shall be under the terms and conditions of
475 | this License, without any additional terms or conditions.
476 | Notwithstanding the above, nothing herein shall supersede or modify
477 | the terms of any separate license agreement you may have executed
478 | with Licensor regarding such Contributions.
479 |
480 | 6. Trademarks. This License does not grant permission to use the trade
481 | names, trademarks, service marks, or product names of the Licensor,
482 | except as required for reasonable and customary use in describing the
483 | origin of the Work and reproducing the content of the NOTICE file.
484 |
485 | 7. Disclaimer of Warranty. Unless required by applicable law or
486 | agreed to in writing, Licensor provides the Work (and each
487 | Contributor provides its Contributions) on an "AS IS" BASIS,
488 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
489 | implied, including, without limitation, any warranties or conditions
490 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
491 | PARTICULAR PURPOSE. You are solely responsible for determining the
492 | appropriateness of using or redistributing the Work and assume any
493 | risks associated with Your exercise of permissions under this License.
494 |
495 | 8. Limitation of Liability. In no event and under no legal theory,
496 | whether in tort (including negligence), contract, or otherwise,
497 | unless required by applicable law (such as deliberate and grossly
498 | negligent acts) or agreed to in writing, shall any Contributor be
499 | liable to You for damages, including any direct, indirect, special,
500 | incidental, or consequential damages of any character arising as a
501 | result of this License or out of the use or inability to use the
502 | Work (including but not limited to damages for loss of goodwill,
503 | work stoppage, computer failure or malfunction, or any and all
504 | other commercial damages or losses), even if such Contributor
505 | has been advised of the possibility of such damages.
506 |
507 | 9. Accepting Warranty or Additional Liability. While redistributing
508 | the Work or Derivative Works thereof, You may choose to offer,
509 | and charge a fee for, acceptance of support, warranty, indemnity,
510 | or other liability obligations and/or rights consistent with this
511 | License. However, in accepting such obligations, You may act only
512 | on Your own behalf and on Your sole responsibility, not on behalf
513 | of any other Contributor, and only if You agree to indemnify,
514 | defend, and hold each Contributor harmless for any liability
515 | incurred by, or claims asserted against, such Contributor by reason
516 | of your accepting any such warranty or additional liability.
517 |
518 | END OF TERMS AND CONDITIONS
519 |
520 | APPENDIX: How to apply the Apache License to your work.
521 |
522 | To apply the Apache License to your work, attach the following
523 | boilerplate notice, with the fields enclosed by brackets "{}"
524 | replaced with your own identifying information. (Don't include
525 | the brackets!) The text should be enclosed in the appropriate
526 | comment syntax for the file format. We also recommend that a
527 | file or class name and description of purpose be included on the
528 | same "printed page" as the copyright notice for easier
529 | identification within third-party archives.
530 |
531 | Copyright 2018 Gregor Martynus and other contributors.
532 |
533 | Licensed under the Apache License, Version 2.0 (the "License");
534 | you may not use this file except in compliance with the License.
535 | You may obtain a copy of the License at
536 |
537 | http://www.apache.org/licenses/LICENSE-2.0
538 |
539 | Unless required by applicable law or agreed to in writing, software
540 | distributed under the License is distributed on an "AS IS" BASIS,
541 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
542 | See the License for the specific language governing permissions and
543 | limitations under the License.
544 |
545 |
546 | call-bind-apply-helpers
547 | MIT
548 | MIT License
549 |
550 | Copyright (c) 2024 Jordan Harband
551 |
552 | Permission is hereby granted, free of charge, to any person obtaining a copy
553 | of this software and associated documentation files (the "Software"), to deal
554 | in the Software without restriction, including without limitation the rights
555 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
556 | copies of the Software, and to permit persons to whom the Software is
557 | furnished to do so, subject to the following conditions:
558 |
559 | The above copyright notice and this permission notice shall be included in all
560 | copies or substantial portions of the Software.
561 |
562 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
563 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
564 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
565 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
566 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
567 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
568 | SOFTWARE.
569 |
570 |
571 | combined-stream
572 | MIT
573 | Copyright (c) 2011 Debuggable Limited
574 |
575 | Permission is hereby granted, free of charge, to any person obtaining a copy
576 | of this software and associated documentation files (the "Software"), to deal
577 | in the Software without restriction, including without limitation the rights
578 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
579 | copies of the Software, and to permit persons to whom the Software is
580 | furnished to do so, subject to the following conditions:
581 |
582 | The above copyright notice and this permission notice shall be included in
583 | all copies or substantial portions of the Software.
584 |
585 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
586 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
587 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
588 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
589 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
590 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
591 | THE SOFTWARE.
592 |
593 |
594 | debug
595 | MIT
596 | (The MIT License)
597 |
598 | Copyright (c) 2014-2017 TJ Holowaychuk
599 | Copyright (c) 2018-2021 Josh Junon
600 |
601 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software
602 | and associated documentation files (the 'Software'), to deal in the Software without restriction,
603 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
604 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
605 | subject to the following conditions:
606 |
607 | The above copyright notice and this permission notice shall be included in all copies or substantial
608 | portions of the Software.
609 |
610 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
611 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
612 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
613 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
614 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
615 |
616 |
617 |
618 | delayed-stream
619 | MIT
620 | Copyright (c) 2011 Debuggable Limited
621 |
622 | Permission is hereby granted, free of charge, to any person obtaining a copy
623 | of this software and associated documentation files (the "Software"), to deal
624 | in the Software without restriction, including without limitation the rights
625 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
626 | copies of the Software, and to permit persons to whom the Software is
627 | furnished to do so, subject to the following conditions:
628 |
629 | The above copyright notice and this permission notice shall be included in
630 | all copies or substantial portions of the Software.
631 |
632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
635 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
636 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
637 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
638 | THE SOFTWARE.
639 |
640 |
641 | dunder-proto
642 | MIT
643 | MIT License
644 |
645 | Copyright (c) 2024 ECMAScript Shims
646 |
647 | Permission is hereby granted, free of charge, to any person obtaining a copy
648 | of this software and associated documentation files (the "Software"), to deal
649 | in the Software without restriction, including without limitation the rights
650 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
651 | copies of the Software, and to permit persons to whom the Software is
652 | furnished to do so, subject to the following conditions:
653 |
654 | The above copyright notice and this permission notice shall be included in all
655 | copies or substantial portions of the Software.
656 |
657 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
658 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
659 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
660 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
661 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
662 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
663 | SOFTWARE.
664 |
665 |
666 | es-define-property
667 | MIT
668 | MIT License
669 |
670 | Copyright (c) 2024 Jordan Harband
671 |
672 | Permission is hereby granted, free of charge, to any person obtaining a copy
673 | of this software and associated documentation files (the "Software"), to deal
674 | in the Software without restriction, including without limitation the rights
675 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
676 | copies of the Software, and to permit persons to whom the Software is
677 | furnished to do so, subject to the following conditions:
678 |
679 | The above copyright notice and this permission notice shall be included in all
680 | copies or substantial portions of the Software.
681 |
682 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
683 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
684 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
685 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
686 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
687 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
688 | SOFTWARE.
689 |
690 |
691 | es-errors
692 | MIT
693 | MIT License
694 |
695 | Copyright (c) 2024 Jordan Harband
696 |
697 | Permission is hereby granted, free of charge, to any person obtaining a copy
698 | of this software and associated documentation files (the "Software"), to deal
699 | in the Software without restriction, including without limitation the rights
700 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
701 | copies of the Software, and to permit persons to whom the Software is
702 | furnished to do so, subject to the following conditions:
703 |
704 | The above copyright notice and this permission notice shall be included in all
705 | copies or substantial portions of the Software.
706 |
707 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
708 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
709 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
710 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
711 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
712 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
713 | SOFTWARE.
714 |
715 |
716 | es-object-atoms
717 | MIT
718 | MIT License
719 |
720 | Copyright (c) 2024 Jordan Harband
721 |
722 | Permission is hereby granted, free of charge, to any person obtaining a copy
723 | of this software and associated documentation files (the "Software"), to deal
724 | in the Software without restriction, including without limitation the rights
725 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
726 | copies of the Software, and to permit persons to whom the Software is
727 | furnished to do so, subject to the following conditions:
728 |
729 | The above copyright notice and this permission notice shall be included in all
730 | copies or substantial portions of the Software.
731 |
732 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
733 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
734 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
735 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
736 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
737 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
738 | SOFTWARE.
739 |
740 |
741 | es-set-tostringtag
742 | MIT
743 | MIT License
744 |
745 | Copyright (c) 2022 ECMAScript Shims
746 |
747 | Permission is hereby granted, free of charge, to any person obtaining a copy
748 | of this software and associated documentation files (the "Software"), to deal
749 | in the Software without restriction, including without limitation the rights
750 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
751 | copies of the Software, and to permit persons to whom the Software is
752 | furnished to do so, subject to the following conditions:
753 |
754 | The above copyright notice and this permission notice shall be included in all
755 | copies or substantial portions of the Software.
756 |
757 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
758 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
759 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
760 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
761 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
762 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
763 | SOFTWARE.
764 |
765 |
766 | fast-content-type-parse
767 | MIT
768 | MIT License
769 |
770 | Copyright (c) 2023 The Fastify Team
771 |
772 | The Fastify team members are listed at https://github.com/fastify/fastify#team
773 | and in the README file.
774 |
775 | Permission is hereby granted, free of charge, to any person obtaining a copy
776 | of this software and associated documentation files (the "Software"), to deal
777 | in the Software without restriction, including without limitation the rights
778 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
779 | copies of the Software, and to permit persons to whom the Software is
780 | furnished to do so, subject to the following conditions:
781 |
782 | The above copyright notice and this permission notice shall be included in all
783 | copies or substantial portions of the Software.
784 |
785 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
786 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
787 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
788 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
789 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
790 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
791 | SOFTWARE.
792 |
793 | follow-redirects
794 | MIT
795 | Copyright 2014–present Olivier Lalonde , James Talmage , Ruben Verborgh
796 |
797 | Permission is hereby granted, free of charge, to any person obtaining a copy of
798 | this software and associated documentation files (the "Software"), to deal in
799 | the Software without restriction, including without limitation the rights to
800 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
801 | of the Software, and to permit persons to whom the Software is furnished to do
802 | so, subject to the following conditions:
803 |
804 | The above copyright notice and this permission notice shall be included in all
805 | copies or substantial portions of the Software.
806 |
807 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
808 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
809 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
810 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
811 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
812 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
813 |
814 |
815 | form-data
816 | MIT
817 | Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
818 |
819 | Permission is hereby granted, free of charge, to any person obtaining a copy
820 | of this software and associated documentation files (the "Software"), to deal
821 | in the Software without restriction, including without limitation the rights
822 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
823 | copies of the Software, and to permit persons to whom the Software is
824 | furnished to do so, subject to the following conditions:
825 |
826 | The above copyright notice and this permission notice shall be included in
827 | all copies or substantial portions of the Software.
828 |
829 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
830 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
831 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
832 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
833 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
834 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
835 | THE SOFTWARE.
836 |
837 |
838 | function-bind
839 | MIT
840 | Copyright (c) 2013 Raynos.
841 |
842 | Permission is hereby granted, free of charge, to any person obtaining a copy
843 | of this software and associated documentation files (the "Software"), to deal
844 | in the Software without restriction, including without limitation the rights
845 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
846 | copies of the Software, and to permit persons to whom the Software is
847 | furnished to do so, subject to the following conditions:
848 |
849 | The above copyright notice and this permission notice shall be included in
850 | all copies or substantial portions of the Software.
851 |
852 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
853 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
854 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
855 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
856 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
857 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
858 | THE SOFTWARE.
859 |
860 |
861 |
862 | get-intrinsic
863 | MIT
864 | MIT License
865 |
866 | Copyright (c) 2020 Jordan Harband
867 |
868 | Permission is hereby granted, free of charge, to any person obtaining a copy
869 | of this software and associated documentation files (the "Software"), to deal
870 | in the Software without restriction, including without limitation the rights
871 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
872 | copies of the Software, and to permit persons to whom the Software is
873 | furnished to do so, subject to the following conditions:
874 |
875 | The above copyright notice and this permission notice shall be included in all
876 | copies or substantial portions of the Software.
877 |
878 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
879 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
880 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
881 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
882 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
883 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
884 | SOFTWARE.
885 |
886 |
887 | get-proto
888 | MIT
889 | MIT License
890 |
891 | Copyright (c) 2025 Jordan Harband
892 |
893 | Permission is hereby granted, free of charge, to any person obtaining a copy
894 | of this software and associated documentation files (the "Software"), to deal
895 | in the Software without restriction, including without limitation the rights
896 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
897 | copies of the Software, and to permit persons to whom the Software is
898 | furnished to do so, subject to the following conditions:
899 |
900 | The above copyright notice and this permission notice shall be included in all
901 | copies or substantial portions of the Software.
902 |
903 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
904 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
905 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
906 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
907 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
908 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
909 | SOFTWARE.
910 |
911 |
912 | gopd
913 | MIT
914 | MIT License
915 |
916 | Copyright (c) 2022 Jordan Harband
917 |
918 | Permission is hereby granted, free of charge, to any person obtaining a copy
919 | of this software and associated documentation files (the "Software"), to deal
920 | in the Software without restriction, including without limitation the rights
921 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
922 | copies of the Software, and to permit persons to whom the Software is
923 | furnished to do so, subject to the following conditions:
924 |
925 | The above copyright notice and this permission notice shall be included in all
926 | copies or substantial portions of the Software.
927 |
928 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
929 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
930 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
931 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
932 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
933 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
934 | SOFTWARE.
935 |
936 |
937 | has-flag
938 | MIT
939 | MIT License
940 |
941 | Copyright (c) Sindre Sorhus (sindresorhus.com)
942 |
943 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
944 |
945 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
946 |
947 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
948 |
949 |
950 | has-symbols
951 | MIT
952 | MIT License
953 |
954 | Copyright (c) 2016 Jordan Harband
955 |
956 | Permission is hereby granted, free of charge, to any person obtaining a copy
957 | of this software and associated documentation files (the "Software"), to deal
958 | in the Software without restriction, including without limitation the rights
959 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
960 | copies of the Software, and to permit persons to whom the Software is
961 | furnished to do so, subject to the following conditions:
962 |
963 | The above copyright notice and this permission notice shall be included in all
964 | copies or substantial portions of the Software.
965 |
966 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
967 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
968 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
969 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
970 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
971 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
972 | SOFTWARE.
973 |
974 |
975 | has-tostringtag
976 | MIT
977 | MIT License
978 |
979 | Copyright (c) 2021 Inspect JS
980 |
981 | Permission is hereby granted, free of charge, to any person obtaining a copy
982 | of this software and associated documentation files (the "Software"), to deal
983 | in the Software without restriction, including without limitation the rights
984 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
985 | copies of the Software, and to permit persons to whom the Software is
986 | furnished to do so, subject to the following conditions:
987 |
988 | The above copyright notice and this permission notice shall be included in all
989 | copies or substantial portions of the Software.
990 |
991 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
992 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
993 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
994 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
995 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
996 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
997 | SOFTWARE.
998 |
999 |
1000 | hasown
1001 | MIT
1002 | MIT License
1003 |
1004 | Copyright (c) Jordan Harband and contributors
1005 |
1006 | Permission is hereby granted, free of charge, to any person obtaining a copy
1007 | of this software and associated documentation files (the "Software"), to deal
1008 | in the Software without restriction, including without limitation the rights
1009 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1010 | copies of the Software, and to permit persons to whom the Software is
1011 | furnished to do so, subject to the following conditions:
1012 |
1013 | The above copyright notice and this permission notice shall be included in all
1014 | copies or substantial portions of the Software.
1015 |
1016 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1017 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1018 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1019 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1020 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1021 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1022 | SOFTWARE.
1023 |
1024 |
1025 | math-intrinsics
1026 | MIT
1027 | MIT License
1028 |
1029 | Copyright (c) 2024 ECMAScript Shims
1030 |
1031 | Permission is hereby granted, free of charge, to any person obtaining a copy
1032 | of this software and associated documentation files (the "Software"), to deal
1033 | in the Software without restriction, including without limitation the rights
1034 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1035 | copies of the Software, and to permit persons to whom the Software is
1036 | furnished to do so, subject to the following conditions:
1037 |
1038 | The above copyright notice and this permission notice shall be included in all
1039 | copies or substantial portions of the Software.
1040 |
1041 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1042 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1043 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1044 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1045 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1046 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1047 | SOFTWARE.
1048 |
1049 |
1050 | mime-db
1051 | MIT
1052 | (The MIT License)
1053 |
1054 | Copyright (c) 2014 Jonathan Ong
1055 | Copyright (c) 2015-2022 Douglas Christopher Wilson
1056 |
1057 | Permission is hereby granted, free of charge, to any person obtaining
1058 | a copy of this software and associated documentation files (the
1059 | 'Software'), to deal in the Software without restriction, including
1060 | without limitation the rights to use, copy, modify, merge, publish,
1061 | distribute, sublicense, and/or sell copies of the Software, and to
1062 | permit persons to whom the Software is furnished to do so, subject to
1063 | the following conditions:
1064 |
1065 | The above copyright notice and this permission notice shall be
1066 | included in all copies or substantial portions of the Software.
1067 |
1068 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
1069 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1070 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1071 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1072 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1073 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1074 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1075 |
1076 |
1077 | mime-types
1078 | MIT
1079 | (The MIT License)
1080 |
1081 | Copyright (c) 2014 Jonathan Ong
1082 | Copyright (c) 2015 Douglas Christopher Wilson
1083 |
1084 | Permission is hereby granted, free of charge, to any person obtaining
1085 | a copy of this software and associated documentation files (the
1086 | 'Software'), to deal in the Software without restriction, including
1087 | without limitation the rights to use, copy, modify, merge, publish,
1088 | distribute, sublicense, and/or sell copies of the Software, and to
1089 | permit persons to whom the Software is furnished to do so, subject to
1090 | the following conditions:
1091 |
1092 | The above copyright notice and this permission notice shall be
1093 | included in all copies or substantial portions of the Software.
1094 |
1095 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
1096 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1097 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1098 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1099 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1100 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1101 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1102 |
1103 |
1104 | ms
1105 | MIT
1106 | The MIT License (MIT)
1107 |
1108 | Copyright (c) 2020 Vercel, Inc.
1109 |
1110 | Permission is hereby granted, free of charge, to any person obtaining a copy
1111 | of this software and associated documentation files (the "Software"), to deal
1112 | in the Software without restriction, including without limitation the rights
1113 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1114 | copies of the Software, and to permit persons to whom the Software is
1115 | furnished to do so, subject to the following conditions:
1116 |
1117 | The above copyright notice and this permission notice shall be included in all
1118 | copies or substantial portions of the Software.
1119 |
1120 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1121 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1122 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1123 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1124 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1125 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1126 | SOFTWARE.
1127 |
1128 |
1129 | proxy-from-env
1130 | MIT
1131 | The MIT License
1132 |
1133 | Copyright (C) 2016-2018 Rob Wu
1134 |
1135 | Permission is hereby granted, free of charge, to any person obtaining a copy of
1136 | this software and associated documentation files (the "Software"), to deal in
1137 | the Software without restriction, including without limitation the rights to
1138 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1139 | of the Software, and to permit persons to whom the Software is furnished to do
1140 | so, subject to the following conditions:
1141 |
1142 | The above copyright notice and this permission notice shall be included in all
1143 | copies or substantial portions of the Software.
1144 |
1145 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1146 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
1147 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
1148 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
1149 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1150 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1151 |
1152 |
1153 | semver
1154 | ISC
1155 | The ISC License
1156 |
1157 | Copyright (c) Isaac Z. Schlueter and Contributors
1158 |
1159 | Permission to use, copy, modify, and/or distribute this software for any
1160 | purpose with or without fee is hereby granted, provided that the above
1161 | copyright notice and this permission notice appear in all copies.
1162 |
1163 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1164 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1165 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1166 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1167 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1168 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
1169 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1170 |
1171 |
1172 | superserial
1173 | MIT
1174 |
1175 | supports-color
1176 | MIT
1177 | MIT License
1178 |
1179 | Copyright (c) Sindre Sorhus (sindresorhus.com)
1180 |
1181 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1182 |
1183 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
1184 |
1185 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1186 |
1187 |
1188 | tunnel
1189 | MIT
1190 | The MIT License (MIT)
1191 |
1192 | Copyright (c) 2012 Koichi Kobayashi
1193 |
1194 | Permission is hereby granted, free of charge, to any person obtaining a copy
1195 | of this software and associated documentation files (the "Software"), to deal
1196 | in the Software without restriction, including without limitation the rights
1197 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1198 | copies of the Software, and to permit persons to whom the Software is
1199 | furnished to do so, subject to the following conditions:
1200 |
1201 | The above copyright notice and this permission notice shall be included in
1202 | all copies or substantial portions of the Software.
1203 |
1204 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1205 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1206 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1207 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1208 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1209 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1210 | THE SOFTWARE.
1211 |
1212 |
1213 | undici
1214 | MIT
1215 | MIT License
1216 |
1217 | Copyright (c) Matteo Collina and Undici contributors
1218 |
1219 | Permission is hereby granted, free of charge, to any person obtaining a copy
1220 | of this software and associated documentation files (the "Software"), to deal
1221 | in the Software without restriction, including without limitation the rights
1222 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1223 | copies of the Software, and to permit persons to whom the Software is
1224 | furnished to do so, subject to the following conditions:
1225 |
1226 | The above copyright notice and this permission notice shall be included in all
1227 | copies or substantial portions of the Software.
1228 |
1229 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1230 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1231 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1232 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1233 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1234 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1235 | SOFTWARE.
1236 |
1237 |
1238 | universal-user-agent
1239 | ISC
1240 | # [ISC License](https://spdx.org/licenses/ISC)
1241 |
1242 | Copyright (c) 2018-2021, Gregor Martynus (https://github.com/gr2m)
1243 |
1244 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
1245 |
1246 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1247 |
--------------------------------------------------------------------------------
/dist/sourcemap-register.js:
--------------------------------------------------------------------------------
1 | (()=>{var e={650:e=>{var r=Object.prototype.toString;var n=typeof Buffer.alloc==="function"&&typeof Buffer.allocUnsafe==="function"&&typeof Buffer.from==="function";function isArrayBuffer(e){return r.call(e).slice(8,-1)==="ArrayBuffer"}function fromArrayBuffer(e,r,t){r>>>=0;var o=e.byteLength-r;if(o<0){throw new RangeError("'offset' is out of bounds")}if(t===undefined){t=o}else{t>>>=0;if(t>o){throw new RangeError("'length' is out of bounds")}}return n?Buffer.from(e.slice(r,r+t)):new Buffer(new Uint8Array(e.slice(r,r+t)))}function fromString(e,r){if(typeof r!=="string"||r===""){r="utf8"}if(!Buffer.isEncoding(r)){throw new TypeError('"encoding" must be a valid string encoding')}return n?Buffer.from(e,r):new Buffer(e,r)}function bufferFrom(e,r,t){if(typeof e==="number"){throw new TypeError('"value" argument must not be a number')}if(isArrayBuffer(e)){return fromArrayBuffer(e,r,t)}if(typeof e==="string"){return fromString(e,r)}return n?Buffer.from(e):new Buffer(e)}e.exports=bufferFrom},274:(e,r,n)=>{var t=n(339);var o=Object.prototype.hasOwnProperty;var i=typeof Map!=="undefined";function ArraySet(){this._array=[];this._set=i?new Map:Object.create(null)}ArraySet.fromArray=function ArraySet_fromArray(e,r){var n=new ArraySet;for(var t=0,o=e.length;t=0){return r}}else{var n=t.toSetString(e);if(o.call(this._set,n)){return this._set[n]}}throw new Error('"'+e+'" is not in the set.')};ArraySet.prototype.at=function ArraySet_at(e){if(e>=0&&e{var t=n(190);var o=5;var i=1<>1;return r?-n:n}r.encode=function base64VLQ_encode(e){var r="";var n;var i=toVLQSigned(e);do{n=i&a;i>>>=o;if(i>0){n|=u}r+=t.encode(n)}while(i>0);return r};r.decode=function base64VLQ_decode(e,r,n){var i=e.length;var s=0;var l=0;var c,p;do{if(r>=i){throw new Error("Expected more digits in base 64 VLQ value.")}p=t.decode(e.charCodeAt(r++));if(p===-1){throw new Error("Invalid base64 digit: "+e.charAt(r-1))}c=!!(p&u);p&=a;s=s+(p<{var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");r.encode=function(e){if(0<=e&&e{r.GREATEST_LOWER_BOUND=1;r.LEAST_UPPER_BOUND=2;function recursiveSearch(e,n,t,o,i,a){var u=Math.floor((n-e)/2)+e;var s=i(t,o[u],true);if(s===0){return u}else if(s>0){if(n-u>1){return recursiveSearch(u,n,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return n1){return recursiveSearch(e,u,t,o,i,a)}if(a==r.LEAST_UPPER_BOUND){return u}else{return e<0?-1:e}}}r.search=function search(e,n,t,o){if(n.length===0){return-1}var i=recursiveSearch(-1,n.length,e,n,t,o||r.GREATEST_LOWER_BOUND);if(i<0){return-1}while(i-1>=0){if(t(n[i],n[i-1],true)!==0){break}--i}return i}},680:(e,r,n)=>{var t=n(339);function generatedPositionAfter(e,r){var n=e.generatedLine;var o=r.generatedLine;var i=e.generatedColumn;var a=r.generatedColumn;return o>n||o==n&&a>=i||t.compareByGeneratedPositionsInflated(e,r)<=0}function MappingList(){this._array=[];this._sorted=true;this._last={generatedLine:-1,generatedColumn:0}}MappingList.prototype.unsortedForEach=function MappingList_forEach(e,r){this._array.forEach(e,r)};MappingList.prototype.add=function MappingList_add(e){if(generatedPositionAfter(this._last,e)){this._last=e;this._array.push(e)}else{this._sorted=false;this._array.push(e)}};MappingList.prototype.toArray=function MappingList_toArray(){if(!this._sorted){this._array.sort(t.compareByGeneratedPositionsInflated);this._sorted=true}return this._array};r.H=MappingList},758:(e,r)=>{function swap(e,r,n){var t=e[r];e[r]=e[n];e[n]=t}function randomIntInRange(e,r){return Math.round(e+Math.random()*(r-e))}function doQuickSort(e,r,n,t){if(n{var t;var o=n(339);var i=n(345);var a=n(274).I;var u=n(449);var s=n(758).U;function SourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}return n.sections!=null?new IndexedSourceMapConsumer(n,r):new BasicSourceMapConsumer(n,r)}SourceMapConsumer.fromSourceMap=function(e,r){return BasicSourceMapConsumer.fromSourceMap(e,r)};SourceMapConsumer.prototype._version=3;SourceMapConsumer.prototype.__generatedMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_generatedMappings",{configurable:true,enumerable:true,get:function(){if(!this.__generatedMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__generatedMappings}});SourceMapConsumer.prototype.__originalMappings=null;Object.defineProperty(SourceMapConsumer.prototype,"_originalMappings",{configurable:true,enumerable:true,get:function(){if(!this.__originalMappings){this._parseMappings(this._mappings,this.sourceRoot)}return this.__originalMappings}});SourceMapConsumer.prototype._charIsMappingSeparator=function SourceMapConsumer_charIsMappingSeparator(e,r){var n=e.charAt(r);return n===";"||n===","};SourceMapConsumer.prototype._parseMappings=function SourceMapConsumer_parseMappings(e,r){throw new Error("Subclasses must implement _parseMappings")};SourceMapConsumer.GENERATED_ORDER=1;SourceMapConsumer.ORIGINAL_ORDER=2;SourceMapConsumer.GREATEST_LOWER_BOUND=1;SourceMapConsumer.LEAST_UPPER_BOUND=2;SourceMapConsumer.prototype.eachMapping=function SourceMapConsumer_eachMapping(e,r,n){var t=r||null;var i=n||SourceMapConsumer.GENERATED_ORDER;var a;switch(i){case SourceMapConsumer.GENERATED_ORDER:a=this._generatedMappings;break;case SourceMapConsumer.ORIGINAL_ORDER:a=this._originalMappings;break;default:throw new Error("Unknown order of iteration.")}var u=this.sourceRoot;a.map((function(e){var r=e.source===null?null:this._sources.at(e.source);r=o.computeSourceURL(u,r,this._sourceMapURL);return{source:r,generatedLine:e.generatedLine,generatedColumn:e.generatedColumn,originalLine:e.originalLine,originalColumn:e.originalColumn,name:e.name===null?null:this._names.at(e.name)}}),this).forEach(e,t)};SourceMapConsumer.prototype.allGeneratedPositionsFor=function SourceMapConsumer_allGeneratedPositionsFor(e){var r=o.getArg(e,"line");var n={source:o.getArg(e,"source"),originalLine:r,originalColumn:o.getArg(e,"column",0)};n.source=this._findSourceIndex(n.source);if(n.source<0){return[]}var t=[];var a=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,i.LEAST_UPPER_BOUND);if(a>=0){var u=this._originalMappings[a];if(e.column===undefined){var s=u.originalLine;while(u&&u.originalLine===s){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}else{var l=u.originalColumn;while(u&&u.originalLine===r&&u.originalColumn==l){t.push({line:o.getArg(u,"generatedLine",null),column:o.getArg(u,"generatedColumn",null),lastColumn:o.getArg(u,"lastGeneratedColumn",null)});u=this._originalMappings[++a]}}}return t};r.SourceMapConsumer=SourceMapConsumer;function BasicSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sources");var u=o.getArg(n,"names",[]);var s=o.getArg(n,"sourceRoot",null);var l=o.getArg(n,"sourcesContent",null);var c=o.getArg(n,"mappings");var p=o.getArg(n,"file",null);if(t!=this._version){throw new Error("Unsupported version: "+t)}if(s){s=o.normalize(s)}i=i.map(String).map(o.normalize).map((function(e){return s&&o.isAbsolute(s)&&o.isAbsolute(e)?o.relative(s,e):e}));this._names=a.fromArray(u.map(String),true);this._sources=a.fromArray(i,true);this._absoluteSources=this._sources.toArray().map((function(e){return o.computeSourceURL(s,e,r)}));this.sourceRoot=s;this.sourcesContent=l;this._mappings=c;this._sourceMapURL=r;this.file=p}BasicSourceMapConsumer.prototype=Object.create(SourceMapConsumer.prototype);BasicSourceMapConsumer.prototype.consumer=SourceMapConsumer;BasicSourceMapConsumer.prototype._findSourceIndex=function(e){var r=e;if(this.sourceRoot!=null){r=o.relative(this.sourceRoot,r)}if(this._sources.has(r)){return this._sources.indexOf(r)}var n;for(n=0;n1){v.source=l+_[1];l+=_[1];v.originalLine=i+_[2];i=v.originalLine;v.originalLine+=1;v.originalColumn=a+_[3];a=v.originalColumn;if(_.length>4){v.name=c+_[4];c+=_[4]}}m.push(v);if(typeof v.originalLine==="number"){d.push(v)}}}s(m,o.compareByGeneratedPositionsDeflated);this.__generatedMappings=m;s(d,o.compareByOriginalPositions);this.__originalMappings=d};BasicSourceMapConsumer.prototype._findMapping=function SourceMapConsumer_findMapping(e,r,n,t,o,a){if(e[n]<=0){throw new TypeError("Line must be greater than or equal to 1, got "+e[n])}if(e[t]<0){throw new TypeError("Column must be greater than or equal to 0, got "+e[t])}return i.search(e,r,o,a)};BasicSourceMapConsumer.prototype.computeColumnSpans=function SourceMapConsumer_computeColumnSpans(){for(var e=0;e=0){var t=this._generatedMappings[n];if(t.generatedLine===r.generatedLine){var i=o.getArg(t,"source",null);if(i!==null){i=this._sources.at(i);i=o.computeSourceURL(this.sourceRoot,i,this._sourceMapURL)}var a=o.getArg(t,"name",null);if(a!==null){a=this._names.at(a)}return{source:i,line:o.getArg(t,"originalLine",null),column:o.getArg(t,"originalColumn",null),name:a}}}return{source:null,line:null,column:null,name:null}};BasicSourceMapConsumer.prototype.hasContentsOfAllSources=function BasicSourceMapConsumer_hasContentsOfAllSources(){if(!this.sourcesContent){return false}return this.sourcesContent.length>=this._sources.size()&&!this.sourcesContent.some((function(e){return e==null}))};BasicSourceMapConsumer.prototype.sourceContentFor=function SourceMapConsumer_sourceContentFor(e,r){if(!this.sourcesContent){return null}var n=this._findSourceIndex(e);if(n>=0){return this.sourcesContent[n]}var t=e;if(this.sourceRoot!=null){t=o.relative(this.sourceRoot,t)}var i;if(this.sourceRoot!=null&&(i=o.urlParse(this.sourceRoot))){var a=t.replace(/^file:\/\//,"");if(i.scheme=="file"&&this._sources.has(a)){return this.sourcesContent[this._sources.indexOf(a)]}if((!i.path||i.path=="/")&&this._sources.has("/"+t)){return this.sourcesContent[this._sources.indexOf("/"+t)]}}if(r){return null}else{throw new Error('"'+t+'" is not in the SourceMap.')}};BasicSourceMapConsumer.prototype.generatedPositionFor=function SourceMapConsumer_generatedPositionFor(e){var r=o.getArg(e,"source");r=this._findSourceIndex(r);if(r<0){return{line:null,column:null,lastColumn:null}}var n={source:r,originalLine:o.getArg(e,"line"),originalColumn:o.getArg(e,"column")};var t=this._findMapping(n,this._originalMappings,"originalLine","originalColumn",o.compareByOriginalPositions,o.getArg(e,"bias",SourceMapConsumer.GREATEST_LOWER_BOUND));if(t>=0){var i=this._originalMappings[t];if(i.source===n.source){return{line:o.getArg(i,"generatedLine",null),column:o.getArg(i,"generatedColumn",null),lastColumn:o.getArg(i,"lastGeneratedColumn",null)}}}return{line:null,column:null,lastColumn:null}};t=BasicSourceMapConsumer;function IndexedSourceMapConsumer(e,r){var n=e;if(typeof e==="string"){n=o.parseSourceMapInput(e)}var t=o.getArg(n,"version");var i=o.getArg(n,"sections");if(t!=this._version){throw new Error("Unsupported version: "+t)}this._sources=new a;this._names=new a;var u={line:-1,column:0};this._sections=i.map((function(e){if(e.url){throw new Error("Support for url field in sections not implemented.")}var n=o.getArg(e,"offset");var t=o.getArg(n,"line");var i=o.getArg(n,"column");if(t{var t=n(449);var o=n(339);var i=n(274).I;var a=n(680).H;function SourceMapGenerator(e){if(!e){e={}}this._file=o.getArg(e,"file",null);this._sourceRoot=o.getArg(e,"sourceRoot",null);this._skipValidation=o.getArg(e,"skipValidation",false);this._sources=new i;this._names=new i;this._mappings=new a;this._sourcesContents=null}SourceMapGenerator.prototype._version=3;SourceMapGenerator.fromSourceMap=function SourceMapGenerator_fromSourceMap(e){var r=e.sourceRoot;var n=new SourceMapGenerator({file:e.file,sourceRoot:r});e.eachMapping((function(e){var t={generated:{line:e.generatedLine,column:e.generatedColumn}};if(e.source!=null){t.source=e.source;if(r!=null){t.source=o.relative(r,t.source)}t.original={line:e.originalLine,column:e.originalColumn};if(e.name!=null){t.name=e.name}}n.addMapping(t)}));e.sources.forEach((function(t){var i=t;if(r!==null){i=o.relative(r,t)}if(!n._sources.has(i)){n._sources.add(i)}var a=e.sourceContentFor(t);if(a!=null){n.setSourceContent(t,a)}}));return n};SourceMapGenerator.prototype.addMapping=function SourceMapGenerator_addMapping(e){var r=o.getArg(e,"generated");var n=o.getArg(e,"original",null);var t=o.getArg(e,"source",null);var i=o.getArg(e,"name",null);if(!this._skipValidation){this._validateMapping(r,n,t,i)}if(t!=null){t=String(t);if(!this._sources.has(t)){this._sources.add(t)}}if(i!=null){i=String(i);if(!this._names.has(i)){this._names.add(i)}}this._mappings.add({generatedLine:r.line,generatedColumn:r.column,originalLine:n!=null&&n.line,originalColumn:n!=null&&n.column,source:t,name:i})};SourceMapGenerator.prototype.setSourceContent=function SourceMapGenerator_setSourceContent(e,r){var n=e;if(this._sourceRoot!=null){n=o.relative(this._sourceRoot,n)}if(r!=null){if(!this._sourcesContents){this._sourcesContents=Object.create(null)}this._sourcesContents[o.toSetString(n)]=r}else if(this._sourcesContents){delete this._sourcesContents[o.toSetString(n)];if(Object.keys(this._sourcesContents).length===0){this._sourcesContents=null}}};SourceMapGenerator.prototype.applySourceMap=function SourceMapGenerator_applySourceMap(e,r,n){var t=r;if(r==null){if(e.file==null){throw new Error("SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, "+'or the source map\'s "file" property. Both were omitted.')}t=e.file}var a=this._sourceRoot;if(a!=null){t=o.relative(a,t)}var u=new i;var s=new i;this._mappings.unsortedForEach((function(r){if(r.source===t&&r.originalLine!=null){var i=e.originalPositionFor({line:r.originalLine,column:r.originalColumn});if(i.source!=null){r.source=i.source;if(n!=null){r.source=o.join(n,r.source)}if(a!=null){r.source=o.relative(a,r.source)}r.originalLine=i.line;r.originalColumn=i.column;if(i.name!=null){r.name=i.name}}}var l=r.source;if(l!=null&&!u.has(l)){u.add(l)}var c=r.name;if(c!=null&&!s.has(c)){s.add(c)}}),this);this._sources=u;this._names=s;e.sources.forEach((function(r){var t=e.sourceContentFor(r);if(t!=null){if(n!=null){r=o.join(n,r)}if(a!=null){r=o.relative(a,r)}this.setSourceContent(r,t)}}),this)};SourceMapGenerator.prototype._validateMapping=function SourceMapGenerator_validateMapping(e,r,n,t){if(r&&typeof r.line!=="number"&&typeof r.column!=="number"){throw new Error("original.line and original.column are not numbers -- you probably meant to omit "+"the original mapping entirely and only map the generated position. If so, pass "+"null for the original mapping instead of an object with empty or null values.")}if(e&&"line"in e&&"column"in e&&e.line>0&&e.column>=0&&!r&&!n&&!t){return}else if(e&&"line"in e&&"column"in e&&r&&"line"in r&&"column"in r&&e.line>0&&e.column>=0&&r.line>0&&r.column>=0&&n){return}else{throw new Error("Invalid mapping: "+JSON.stringify({generated:e,source:n,original:r,name:t}))}};SourceMapGenerator.prototype._serializeMappings=function SourceMapGenerator_serializeMappings(){var e=0;var r=1;var n=0;var i=0;var a=0;var u=0;var s="";var l;var c;var p;var f;var g=this._mappings.toArray();for(var h=0,d=g.length;h0){if(!o.compareByGeneratedPositionsInflated(c,g[h-1])){continue}l+=","}}l+=t.encode(c.generatedColumn-e);e=c.generatedColumn;if(c.source!=null){f=this._sources.indexOf(c.source);l+=t.encode(f-u);u=f;l+=t.encode(c.originalLine-1-i);i=c.originalLine-1;l+=t.encode(c.originalColumn-n);n=c.originalColumn;if(c.name!=null){p=this._names.indexOf(c.name);l+=t.encode(p-a);a=p}}s+=l}return s};SourceMapGenerator.prototype._generateSourcesContent=function SourceMapGenerator_generateSourcesContent(e,r){return e.map((function(e){if(!this._sourcesContents){return null}if(r!=null){e=o.relative(r,e)}var n=o.toSetString(e);return Object.prototype.hasOwnProperty.call(this._sourcesContents,n)?this._sourcesContents[n]:null}),this)};SourceMapGenerator.prototype.toJSON=function SourceMapGenerator_toJSON(){var e={version:this._version,sources:this._sources.toArray(),names:this._names.toArray(),mappings:this._serializeMappings()};if(this._file!=null){e.file=this._file}if(this._sourceRoot!=null){e.sourceRoot=this._sourceRoot}if(this._sourcesContents){e.sourcesContent=this._generateSourcesContent(e.sources,e.sourceRoot)}return e};SourceMapGenerator.prototype.toString=function SourceMapGenerator_toString(){return JSON.stringify(this.toJSON())};r.h=SourceMapGenerator},351:(e,r,n)=>{var t;var o=n(591).h;var i=n(339);var a=/(\r?\n)/;var u=10;var s="$$$isSourceNode$$$";function SourceNode(e,r,n,t,o){this.children=[];this.sourceContents={};this.line=e==null?null:e;this.column=r==null?null:r;this.source=n==null?null:n;this.name=o==null?null:o;this[s]=true;if(t!=null)this.add(t)}SourceNode.fromStringWithSourceMap=function SourceNode_fromStringWithSourceMap(e,r,n){var t=new SourceNode;var o=e.split(a);var u=0;var shiftNextLine=function(){var e=getNextLine();var r=getNextLine()||"";return e+r;function getNextLine(){return u=0;r--){this.prepend(e[r])}}else if(e[s]||typeof e==="string"){this.children.unshift(e)}else{throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got "+e)}return this};SourceNode.prototype.walk=function SourceNode_walk(e){var r;for(var n=0,t=this.children.length;n0){r=[];for(n=0;n{function getArg(e,r,n){if(r in e){return e[r]}else if(arguments.length===3){return n}else{throw new Error('"'+r+'" is a required argument.')}}r.getArg=getArg;var n=/^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;var t=/^data:.+\,.+$/;function urlParse(e){var r=e.match(n);if(!r){return null}return{scheme:r[1],auth:r[2],host:r[3],port:r[4],path:r[5]}}r.urlParse=urlParse;function urlGenerate(e){var r="";if(e.scheme){r+=e.scheme+":"}r+="//";if(e.auth){r+=e.auth+"@"}if(e.host){r+=e.host}if(e.port){r+=":"+e.port}if(e.path){r+=e.path}return r}r.urlGenerate=urlGenerate;function normalize(e){var n=e;var t=urlParse(e);if(t){if(!t.path){return e}n=t.path}var o=r.isAbsolute(n);var i=n.split(/\/+/);for(var a,u=0,s=i.length-1;s>=0;s--){a=i[s];if(a==="."){i.splice(s,1)}else if(a===".."){u++}else if(u>0){if(a===""){i.splice(s+1,u);u=0}else{i.splice(s,2);u--}}}n=i.join("/");if(n===""){n=o?"/":"."}if(t){t.path=n;return urlGenerate(t)}return n}r.normalize=normalize;function join(e,r){if(e===""){e="."}if(r===""){r="."}var n=urlParse(r);var o=urlParse(e);if(o){e=o.path||"/"}if(n&&!n.scheme){if(o){n.scheme=o.scheme}return urlGenerate(n)}if(n||r.match(t)){return r}if(o&&!o.host&&!o.path){o.host=r;return urlGenerate(o)}var i=r.charAt(0)==="/"?r:normalize(e.replace(/\/+$/,"")+"/"+r);if(o){o.path=i;return urlGenerate(o)}return i}r.join=join;r.isAbsolute=function(e){return e.charAt(0)==="/"||n.test(e)};function relative(e,r){if(e===""){e="."}e=e.replace(/\/$/,"");var n=0;while(r.indexOf(e+"/")!==0){var t=e.lastIndexOf("/");if(t<0){return r}e=e.slice(0,t);if(e.match(/^([^\/]+:\/)?\/*$/)){return r}++n}return Array(n+1).join("../")+r.substr(e.length+1)}r.relative=relative;var o=function(){var e=Object.create(null);return!("__proto__"in e)}();function identity(e){return e}function toSetString(e){if(isProtoString(e)){return"$"+e}return e}r.toSetString=o?identity:toSetString;function fromSetString(e){if(isProtoString(e)){return e.slice(1)}return e}r.fromSetString=o?identity:fromSetString;function isProtoString(e){if(!e){return false}var r=e.length;if(r<9){return false}if(e.charCodeAt(r-1)!==95||e.charCodeAt(r-2)!==95||e.charCodeAt(r-3)!==111||e.charCodeAt(r-4)!==116||e.charCodeAt(r-5)!==111||e.charCodeAt(r-6)!==114||e.charCodeAt(r-7)!==112||e.charCodeAt(r-8)!==95||e.charCodeAt(r-9)!==95){return false}for(var n=r-10;n>=0;n--){if(e.charCodeAt(n)!==36){return false}}return true}function compareByOriginalPositions(e,r,n){var t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0||n){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0){return t}t=e.generatedLine-r.generatedLine;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByOriginalPositions=compareByOriginalPositions;function compareByGeneratedPositionsDeflated(e,r,n){var t=e.generatedLine-r.generatedLine;if(t!==0){return t}t=e.generatedColumn-r.generatedColumn;if(t!==0||n){return t}t=strcmp(e.source,r.source);if(t!==0){return t}t=e.originalLine-r.originalLine;if(t!==0){return t}t=e.originalColumn-r.originalColumn;if(t!==0){return t}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsDeflated=compareByGeneratedPositionsDeflated;function strcmp(e,r){if(e===r){return 0}if(e===null){return 1}if(r===null){return-1}if(e>r){return 1}return-1}function compareByGeneratedPositionsInflated(e,r){var n=e.generatedLine-r.generatedLine;if(n!==0){return n}n=e.generatedColumn-r.generatedColumn;if(n!==0){return n}n=strcmp(e.source,r.source);if(n!==0){return n}n=e.originalLine-r.originalLine;if(n!==0){return n}n=e.originalColumn-r.originalColumn;if(n!==0){return n}return strcmp(e.name,r.name)}r.compareByGeneratedPositionsInflated=compareByGeneratedPositionsInflated;function parseSourceMapInput(e){return JSON.parse(e.replace(/^\)]}'[^\n]*\n/,""))}r.parseSourceMapInput=parseSourceMapInput;function computeSourceURL(e,r,n){r=r||"";if(e){if(e[e.length-1]!=="/"&&r[0]!=="/"){e+="/"}r=e+r}if(n){var t=urlParse(n);if(!t){throw new Error("sourceMapURL could not be parsed")}if(t.path){var o=t.path.lastIndexOf("/");if(o>=0){t.path=t.path.substring(0,o+1)}}r=join(urlGenerate(t),r)}return normalize(r)}r.computeSourceURL=computeSourceURL},997:(e,r,n)=>{n(591).h;r.SourceMapConsumer=n(952).SourceMapConsumer;n(351)},284:(e,r,n)=>{e=n.nmd(e);var t=n(997).SourceMapConsumer;var o=n(17);var i;try{i=n(147);if(!i.existsSync||!i.readFileSync){i=null}}catch(e){}var a=n(650);function dynamicRequire(e,r){return e.require(r)}var u=false;var s=false;var l=false;var c="auto";var p={};var f={};var g=/^data:application\/json[^,]+base64,/;var h=[];var d=[];function isInBrowser(){if(c==="browser")return true;if(c==="node")return false;return typeof window!=="undefined"&&typeof XMLHttpRequest==="function"&&!(window.require&&window.module&&window.process&&window.process.type==="renderer")}function hasGlobalProcessEventEmitter(){return typeof process==="object"&&process!==null&&typeof process.on==="function"}function globalProcessVersion(){if(typeof process==="object"&&process!==null){return process.version}else{return""}}function globalProcessStderr(){if(typeof process==="object"&&process!==null){return process.stderr}}function globalProcessExit(e){if(typeof process==="object"&&process!==null&&typeof process.exit==="function"){return process.exit(e)}}function handlerExec(e){return function(r){for(var n=0;n"}var n=this.getLineNumber();if(n!=null){r+=":"+n;var t=this.getColumnNumber();if(t){r+=":"+t}}}var o="";var i=this.getFunctionName();var a=true;var u=this.isConstructor();var s=!(this.isToplevel()||u);if(s){var l=this.getTypeName();if(l==="[object Object]"){l="null"}var c=this.getMethodName();if(i){if(l&&i.indexOf(l)!=0){o+=l+"."}o+=i;if(c&&i.indexOf("."+c)!=i.length-c.length-1){o+=" [as "+c+"]"}}else{o+=l+"."+(c||"")}}else if(u){o+="new "+(i||"")}else if(i){o+=i}else{o+=r;a=false}if(a){o+=" ("+r+")"}return o}function cloneCallSite(e){var r={};Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach((function(n){r[n]=/^(?:is|get)/.test(n)?function(){return e[n].call(e)}:e[n]}));r.toString=CallSiteToString;return r}function wrapCallSite(e,r){if(r===undefined){r={nextPosition:null,curPosition:null}}if(e.isNative()){r.curPosition=null;return e}var n=e.getFileName()||e.getScriptNameOrSourceURL();if(n){var t=e.getLineNumber();var o=e.getColumnNumber()-1;var i=/^v(10\.1[6-9]|10\.[2-9][0-9]|10\.[0-9]{3,}|1[2-9]\d*|[2-9]\d|\d{3,}|11\.11)/;var a=i.test(globalProcessVersion())?0:62;if(t===1&&o>a&&!isInBrowser()&&!e.isEval()){o-=a}var u=mapSourcePosition({source:n,line:t,column:o});r.curPosition=u;e=cloneCallSite(e);var s=e.getFunctionName;e.getFunctionName=function(){if(r.nextPosition==null){return s()}return r.nextPosition.name||s()};e.getFileName=function(){return u.source};e.getLineNumber=function(){return u.line};e.getColumnNumber=function(){return u.column+1};e.getScriptNameOrSourceURL=function(){return u.source};return e}var l=e.isEval()&&e.getEvalOrigin();if(l){l=mapEvalOrigin(l);e=cloneCallSite(e);e.getEvalOrigin=function(){return l};return e}return e}function prepareStackTrace(e,r){if(l){p={};f={}}var n=e.name||"Error";var t=e.message||"";var o=n+": "+t;var i={nextPosition:null,curPosition:null};var a=[];for(var u=r.length-1;u>=0;u--){a.push("\n at "+wrapCallSite(r[u],i));i.nextPosition=i.curPosition}i.curPosition=i.nextPosition=null;return o+a.reverse().join("")}function getErrorSource(e){var r=/\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(e.stack);if(r){var n=r[1];var t=+r[2];var o=+r[3];var a=p[n];if(!a&&i&&i.existsSync(n)){try{a=i.readFileSync(n,"utf8")}catch(e){a=""}}if(a){var u=a.split(/(?:\r\n|\r|\n)/)[t-1];if(u){return n+":"+t+"\n"+u+"\n"+new Array(o).join(" ")+"^"}}}return null}function printErrorAndExit(e){var r=getErrorSource(e);var n=globalProcessStderr();if(n&&n._handle&&n._handle.setBlocking){n._handle.setBlocking(true)}if(r){console.error();console.error(r)}console.error(e.stack);globalProcessExit(1)}function shimEmitUncaughtException(){var e=process.emit;process.emit=function(r){if(r==="uncaughtException"){var n=arguments[1]&&arguments[1].stack;var t=this.listeners(r).length>0;if(n&&!t){return printErrorAndExit(arguments[1])}}return e.apply(this,arguments)}}var S=h.slice(0);var _=d.slice(0);r.wrapCallSite=wrapCallSite;r.getErrorSource=getErrorSource;r.mapSourcePosition=mapSourcePosition;r.retrieveSourceMap=v;r.install=function(r){r=r||{};if(r.environment){c=r.environment;if(["node","browser","auto"].indexOf(c)===-1){throw new Error("environment "+c+" was unknown. Available options are {auto, browser, node}")}}if(r.retrieveFile){if(r.overrideRetrieveFile){h.length=0}h.unshift(r.retrieveFile)}if(r.retrieveSourceMap){if(r.overrideRetrieveSourceMap){d.length=0}d.unshift(r.retrieveSourceMap)}if(r.hookRequire&&!isInBrowser()){var n=dynamicRequire(e,"module");var t=n.prototype._compile;if(!t.__sourceMapSupport){n.prototype._compile=function(e,r){p[r]=e;f[r]=undefined;return t.call(this,e,r)};n.prototype._compile.__sourceMapSupport=true}}if(!l){l="emptyCacheBetweenOperations"in r?r.emptyCacheBetweenOperations:false}if(!u){u=true;Error.prepareStackTrace=prepareStackTrace}if(!s){var o="handleUncaughtExceptions"in r?r.handleUncaughtExceptions:true;try{var i=dynamicRequire(e,"worker_threads");if(i.isMainThread===false){o=false}}catch(e){}if(o&&hasGlobalProcessEventEmitter()){s=true;shimEmitUncaughtException()}}};r.resetRetrieveHandlers=function(){h.length=0;d.length=0;h=S.slice(0);d=_.slice(0);v=handlerExec(d);m=handlerExec(h)}},147:e=>{"use strict";e.exports=require("fs")},17:e=>{"use strict";e.exports=require("path")}};var r={};function __webpack_require__(n){var t=r[n];if(t!==undefined){return t.exports}var o=r[n]={id:n,loaded:false,exports:{}};var i=true;try{e[n](o,o.exports,__webpack_require__);i=false}finally{if(i)delete r[n]}o.loaded=true;return o.exports}(()=>{__webpack_require__.nmd=e=>{e.paths=[];if(!e.children)e.children=[];return e}})();if(typeof __webpack_require__!=="undefined")__webpack_require__.ab=__dirname+"/";var n={};(()=>{__webpack_require__(284).install()})();module.exports=n})();
--------------------------------------------------------------------------------
/docs/listendev_pro_jwt_api_key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listendev/action/49b8e3dcdec362c3603fb4e79a366e7e30b8451d/docs/listendev_pro_jwt_api_key.png
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | clearMocks: true,
3 | moduleFileExtensions: ["js", "ts"],
4 | testEnvironment: "node",
5 | testMatch: ["**/*.test.ts"],
6 | transform: {
7 | "^.+\\.ts$": "ts-jest",
8 | },
9 | verbose: true,
10 | setupFilesAfterEnv: ["jest-os-detection"],
11 | };
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@listendev/action",
3 | "version": "0.19.0",
4 | "description": "Get real-time dependency insights in your pull requests",
5 | "main": "dist/index.js",
6 | "scripts": {
7 | "test": "jest",
8 | "format": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --write **/*.{ts,yml,yaml}",
9 | "format-check": "prettier --no-error-on-unmatched-pattern --config ./.prettierrc.js --check **/*.{ts,yml,yaml}",
10 | "lint": "eslint --config ./.eslintrc.js **/*.ts",
11 | "lint:fix": "eslint --config ./.eslintrc.js **/*.ts --fix",
12 | "build": "tsc && ncc build --source-map --license licenses.txt -o dist/ src/main.ts"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "git+https://github.com/listendev/action.git"
17 | },
18 | "keywords": [
19 | "actions",
20 | "github",
21 | "lstn",
22 | "listendev",
23 | "o11y",
24 | "security",
25 | "pullrequests",
26 | "annotations",
27 | "suggestions",
28 | "deps",
29 | "dependencies",
30 | "supply",
31 | "chain",
32 | "security"
33 | ],
34 | "private": true,
35 | "author": "The listen.dev team ",
36 | "license": "Apache-2.0",
37 | "bugs": {
38 | "url": "https://github.com/listendev/action/issues"
39 | },
40 | "homepage": "https://github.com/listendev/action#readme",
41 | "dependencies": {
42 | "@actions/core": "^1.10.0",
43 | "@actions/exec": "^1.1.1",
44 | "@actions/http-client": "^2.1.0",
45 | "@actions/io": "^1.1.3",
46 | "@actions/tool-cache": "^2.0.1",
47 | "@octokit/rest": "^21.0.2",
48 | "axios": "^1.7.9",
49 | "semver": "^7.6.3",
50 | "superserial": "^0.3.5"
51 | },
52 | "devDependencies": {
53 | "@types/jest": "^29.4.4",
54 | "@types/node": "^18.15.3",
55 | "@types/semver": "^7.3.13",
56 | "@typescript-eslint/eslint-plugin": "^5.55.0",
57 | "@typescript-eslint/parser": "^5.55.0",
58 | "@vercel/ncc": "^0.36.1",
59 | "eslint": "^8.36.0",
60 | "eslint-config-prettier": "^8.7.0",
61 | "eslint-plugin-jest": "^27.2.1",
62 | "eslint-plugin-node": "^11.1.0",
63 | "jest": "^29.5.0",
64 | "jest-os-detection": "^1.3.1",
65 | "prettier": "^2.8.5",
66 | "ts-jest": "^29.0.5",
67 | "typescript": "^4.9.5"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/reviewpad.yml:
--------------------------------------------------------------------------------
1 | extends:
2 | - https://github.com/listendev/.github/blob/main/reviewpad/common.yml
3 |
4 | # For more details see https://docs.reviewpad.com/guides/syntax#label.
5 | labels:
6 | "bump:major":
7 | description: Marks a pull request as introducing a breaking change
8 | color: "#fc0324"
9 | "bump:minor":
10 | description: Marks a pull request as introducing a minor change
11 | color: "#ae40b8"
12 | "bump:patch":
13 | description: Marks a pull request as introducing a patch
14 | color: "#ad8fb0"
15 |
16 |
17 | rules:
18 | - name: docs-changes
19 | spec: $hasFileExtensions([".md", ".txt"]) || $matchString("^docs(\([A-Za-z0-9_\/]+\))??:.+$", $title())
20 | - name: ci-changes
21 | spec: $hasFilePattern(".github/**") || $hasFileName("reviewpad.yml") || $matchString("^ci(\([A-Za-z0-9_\/]+\))??:.+$", $title())
22 | - name: deps-changes
23 | spec: $hasFileName("package.json") || $hasFileName("package-lock.json") || $matchString("^build\(deps\)\/.+", $title())
24 | - name: feat-changes
25 | spec: $matchString("^feat(\([A-Za-z0-9_\/]+\))??:.+$", $title())
26 | - name: fix-changes
27 | spec: $matchString("^fix(\([A-Za-z0-9_\/]+\))??:.+$", $title())
28 | - name: breaking-changes
29 | spec: $matchString("^([A-Za-z0-9_]+)??(\([A-Za-z0-9_\/]+\))??!:.+$", $title())
30 | - name: exclude-changes
31 | spec: $matchString("^(chore|refactor|revert|perf|test)(\([A-Za-z0-9_\/]+\))??:.+$", $title())
32 | - name: by-bot
33 | spec: $matchString("^(dependabot|github-actions).*$", $author())
34 | - name: build-changes
35 | spec: $hasFilePattern("make/**") || $matchString("^build(\([A-Za-z0-9_\/]+\))??:.+$", $title()) || $matchString("^build\/.+", $head())
36 | - name: test-changes
37 | spec: $hasFilePattern("__tests__/**") || $hasFileName(".github/workflows/test.yaml")
38 |
39 |
40 | groups:
41 | - name: ignore-patterns
42 | spec: '["package-lock.json", "dist/**"]'
43 |
44 | # For more details see https://docs.reviewpad.com/guides/syntax#workflow.
45 | workflows:
46 | # This workflow labels pull requests based on the pull request change type.
47 | # This helps pick pull requests based on their change type.
48 | - name: pulls-labelling
49 | description: Label pull requests
50 | always-run: true
51 | if:
52 | - rule: feat-changes
53 | extra-actions:
54 | - $addLabel("enhancement")
55 | - $addLabel("bump:minor")
56 | - $removeLabel("bump:patch")
57 | - rule: docs-changes
58 | extra-actions:
59 | - $addLabel("documentation")
60 | - $addLabel("bump:patch")
61 | - rule: ci-changes
62 | extra-actions:
63 | - $addLabel("ci")
64 | - $addLabel("bump:patch")
65 | - rule: deps-changes
66 | extra-actions:
67 | - $addLabel("dependencies")
68 | - $addLabel("bump:patch")
69 | - rule: test-changes
70 | extra-actions:
71 | - $addLabel("test")
72 | - $addLabel("bump:patch")
73 | - rule: build-changes
74 | extra-actions:
75 | - $addLabel("build")
76 | - $addLabel("bump:patch")
77 | - rule: fix-changes
78 | extra-actions:
79 | - $addLabel("bug")
80 | - $addLabel("bump:patch")
81 | - rule: breaking-changes
82 | extra-actions:
83 | - $addLabel("breaking-change")
84 | - $addLabel("bump:major")
85 | - $removeLabels("bump:minor", "bump:patch")
86 | - rule: exclude-changes
87 | extra-actions:
88 | - $addLabel("no-releasenotes")
89 | - $removeLabels("bump:major", "bump:minor", "bump:patch")
90 | - rule: by-bot
91 | extra-actions:
92 | - $addLabel("no-releasenotes")
93 | - $removeLabels("bump:major", "bump:minor", "bump:patch")
94 | - rule: $isWaitingForReview()
95 | extra-actions:
96 | - $addLabel("needs-review")
97 | - rule: $isWaitingForReview() == false
98 | extra-actions:
99 | - $removeLabel("needs-review")
100 |
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | import * as core from '@actions/core';
2 |
3 | /**
4 | * EavesdropMustRunAlone is true when the eavesdrop tool is the only one that must run.
5 | */
6 | export const EavesdropMustRunAlone: boolean =
7 | core.getInput('runtime') == 'only';
8 |
9 | /**
10 | * EavesdropMustRun is true when the eavesdrop tool will run, either alone or together with other tools.
11 | */
12 | export const EavesdropMustRun: boolean =
13 | core.getInput('runtime') == 'true' || EavesdropMustRunAlone;
14 |
--------------------------------------------------------------------------------
/src/eavesdrop.ts:
--------------------------------------------------------------------------------
1 | import * as semver from 'semver';
2 | import * as core from '@actions/core';
3 | import * as exec from '@actions/exec';
4 | import {daemonsReload} from './systemctl';
5 | import {checkPath} from './utils';
6 | import {Writable} from 'stream';
7 | import {getArch, getPlat, tagToVersion} from './install';
8 | import * as tc from '@actions/tool-cache';
9 | import * as path from 'path';
10 | import * as io from '@actions/io';
11 | import * as fs from 'fs';
12 | import * as state from './state';
13 | import {Serializer, toSerialize, toDeserialize} from 'superserial';
14 | import {EavesdropMustRun} from './constants';
15 |
16 | const STATE_ID = 'eavesdrop_instance';
17 |
18 | export class Tool {
19 | private lstn: string;
20 | private version: string;
21 | private name: string;
22 | private cliEnablingCommand: string[];
23 | private installed = false;
24 |
25 | // tagMap maps the lstn tags to the eavesdrop tool versions.
26 | public static tagMap: Record = {
27 | 'v0.20.0': 'v1.9',
28 | 'v0.19.0': 'v1.5',
29 | 'v0.18.0': 'v1.2',
30 | 'v0.17.0': 'v1.1',
31 | 'v0.16.0': 'v1.0',
32 | 'v0.15.0': 'v0.6',
33 | 'v0.14.0': 'v0.4',
34 | 'v0.13.2': 'v0.3',
35 | 'v0.13.1': 'v0.1',
36 | 'v0.13.0': 'v0.1'
37 | } as const;
38 |
39 | serialize() {
40 | return s.serialize(this);
41 | }
42 |
43 | [toSerialize]() {
44 | return {
45 | lstn: this.lstn,
46 | version: this.version,
47 | name: this.name,
48 | cliEnablingCommand: this.cliEnablingCommand,
49 | installed: this.installed
50 | };
51 | }
52 |
53 | [toDeserialize](value: {
54 | lstn: string;
55 | version: string;
56 | name: string;
57 | cliEnablingCommand: string[];
58 | installed: boolean;
59 | }) {
60 | this.lstn = value.lstn;
61 | this.version = value.version;
62 | this.name = value.name;
63 | this.cliEnablingCommand = value.cliEnablingCommand;
64 | this.installed = value.installed;
65 | }
66 |
67 | private initCliVersion(): string {
68 | const versions = Object.keys(Tool.tagMap);
69 | const v = core.getInput('lstn');
70 | if (v === 'dev') {
71 | return 'dev';
72 | }
73 |
74 | const tag = v == 'latest' ? versions[0] : core.getInput('lstn');
75 | const version = semver.coerce(tag);
76 | if (!version || !semver.valid(version)) {
77 | throw new Error(`invalid lstn version (${tag})`);
78 | }
79 |
80 | if (!versions.includes(tag.startsWith('v') ? tag : `v${tag}`)) {
81 | throw new Error(`unsupported lstn version (${tag})`);
82 | }
83 |
84 | return version.format();
85 | }
86 |
87 | private initVersion(): string {
88 | if (!EavesdropMustRun) return '';
89 |
90 | const explicit = core.getInput('eavesdrop_version');
91 | if (!explicit) {
92 | if (this.lstn === 'dev') {
93 | // if we are using dev CLI we can use the nightly version of the eavesdrop tool
94 | return 'v0.0.0';
95 | }
96 |
97 | return Tool.tagMap[
98 | this.lstn.startsWith('v') ? this.lstn : `v${this.lstn}`
99 | ];
100 | }
101 | const v = explicit.startsWith('v') ? explicit : `v${explicit}`;
102 |
103 | const custom = semver.coerce(v);
104 | if (!custom || !semver.valid(custom)) {
105 | throw new Error(`invalid custom eavesdrop tool version (${custom})`);
106 | }
107 |
108 | if (
109 | !semver.eq(custom, 'v0.0.0') &&
110 | !Object.values(Tool.tagMap).includes(v)
111 | ) {
112 | throw new Error(`unsupported custom eavesdrop tool version (${v})`);
113 | }
114 |
115 | if (this.lstn === 'dev') {
116 | // skip check with dev lstn CLI
117 | return custom.format();
118 | }
119 |
120 | const lstnv = semver.coerce(this.lstn);
121 | if (!lstnv || !semver.valid(lstnv)) {
122 | throw new Error(`invalid lstn version (${this.lstn})`);
123 | }
124 |
125 | // Check that the explicit version is compatible with the current lstn version
126 | if (!semver.eq(custom, 'v0.0.0')) {
127 | if (semver.gte(lstnv, 'v0.16.0')) {
128 | // At least lstn v0.16.0 for eavesdrop tool versions >= v0.8
129 | if (semver.lt(custom, 'v0.8.0')) {
130 | throw new Error(
131 | `custom eavesdrop tool version (${v}) cannot work with lstn versions >= v0.16.0`
132 | );
133 | }
134 | } else {
135 | // Max lstn v0.15.0 for custom eavesdrop versions up to v0.6
136 | if (semver.gte(custom, 'v0.8.0')) {
137 | throw new Error(
138 | `custom eavesdrop tool version (${v}) cannot work with lstn versions < v0.16.0`
139 | );
140 | }
141 | }
142 | } else {
143 | // Nightly (v0.0) only works with lstn >= v0.16.0
144 | if (semver.lt(lstnv, 'v0.16.0')) {
145 | throw new Error(
146 | `nightly eavesdrop tool version (${v}) cannot work with lstn versions < v0.16.0`
147 | );
148 | }
149 | }
150 |
151 | const res = custom.format();
152 |
153 | return res.startsWith('v') ? res : `v${res}`;
154 | }
155 |
156 | private initName(): string {
157 | if (!EavesdropMustRun) return '';
158 |
159 | const version = semver.coerce(this.version);
160 | if (!version || !semver.valid(version)) {
161 | throw new Error(`invalid eavesdrop tool version (${this.version})`);
162 | }
163 |
164 | // Switch to jibril from v0.8 onwards
165 | // Also, use jibril nightly for v0.0
166 | if (semver.eq(version, 'v0.0.0') || semver.gte(version, 'v0.8.0')) {
167 | return 'jibril';
168 | }
169 |
170 | return 'argus';
171 | }
172 |
173 | private initCliEnablingCommand(): string[] {
174 | if (!EavesdropMustRun) return [];
175 |
176 | if (this.lstn === 'dev') {
177 | // skip check with dev lstn CLI
178 | return ['ci', 'enable'];
179 | }
180 |
181 | const lstnv = semver.coerce(this.lstn);
182 | if (!lstnv || !semver.valid(lstnv)) {
183 | throw new Error(`invalid lstn version (${this.lstn})`);
184 | }
185 |
186 | // Switch to `ci enable` from lstn v0.16.0 onwards
187 | if (semver.gte(lstnv, 'v0.16.0')) {
188 | return ['ci', 'enable'];
189 | }
190 |
191 | return ['ci'];
192 | }
193 |
194 | private async getEnvironmentFile() {
195 | const environmentFile = `/var/run/${this.name}/default`;
196 | const res = await checkPath(environmentFile, true);
197 | if (!res.exists) {
198 | return {exists: false, content: ''};
199 | }
200 |
201 | if (!res.isFile) {
202 | return {exists: false, content: ''};
203 | }
204 |
205 | let file = '';
206 | const options: exec.ExecOptions = {
207 | // Redirect stdout to the writable stream
208 | outStream: new Writable({
209 | write(chunk, encoding, callback) {
210 | file += chunk.toString();
211 | callback();
212 | }
213 | })
214 | };
215 | try {
216 | await exec.exec('sudo', ['cat', environmentFile], options);
217 | } catch (error) {
218 | return {exists: true, content: ''};
219 | }
220 |
221 | return {exists: true, content: file};
222 | }
223 |
224 | private async download(directory: string) {
225 | // The eavesdrop tool only runs on linux amd64
226 | const plat = getPlat(process.platform.toString());
227 | switch (plat) {
228 | case 'linux':
229 | break;
230 | default:
231 | throw new Error(`unsupported platform: ${plat}`);
232 | }
233 | const arch = getArch(process.arch.toString());
234 | switch (arch) {
235 | case 'amd64':
236 | break;
237 | default:
238 | throw new Error(`unsupported arch: ${arch}`);
239 | }
240 |
241 | const tag = semver.coerce(this.version);
242 | if (!tag || !semver.valid(tag)) {
243 | throw new Error(`invalid eavesdrop version to download (${tag})`);
244 | }
245 |
246 | const owner = 'listendev';
247 | const repo = `${this.name}-releases`;
248 | const vers = await tagToVersion(
249 | `v${semver.major(tag)}.${semver.minor(tag)}`,
250 | owner,
251 | repo
252 | );
253 | const url = `https://github.com/${owner}/${repo}/releases/download/v${vers}/loader`;
254 |
255 | core.info(`downloading from ${url}`);
256 |
257 | const download = await tc.downloadTool(url);
258 |
259 | core.info(`preparing binary...`);
260 |
261 | const dest = path.join(directory, this.name);
262 | await io.mv(download, dest);
263 | fs.chmodSync(dest, 0o755);
264 |
265 | return dest;
266 | }
267 |
268 | constructor() {
269 | this.lstn = this.initCliVersion();
270 | core.info(`lstn version: ${this.lstn}`);
271 |
272 | this.version = this.initVersion();
273 | core.info(`eavesdrop version: ${this.version}`);
274 |
275 | this.name = this.initName();
276 | core.info(`eavesdrop name: ${this.name}`);
277 |
278 | this.cliEnablingCommand = this.initCliEnablingCommand();
279 | }
280 |
281 | public getVersion(): string {
282 | return this.version;
283 | }
284 |
285 | public getName(): string {
286 | return this.name;
287 | }
288 |
289 | public getCliEnablingCommand(): string[] {
290 | return this.cliEnablingCommand;
291 | }
292 |
293 | public isInstalled(): boolean {
294 | return this.installed;
295 | }
296 |
297 | public async install(tmpdir: string, into = '/usr/bin/') {
298 | if (!EavesdropMustRun) {
299 | return '';
300 | }
301 |
302 | return await core.group(
303 | `👁️🗨️ Installing ${this.name}... https://listen.dev`,
304 | async () => {
305 | // Install the eavesdrop tool for lstn
306 | const location = await this.download(tmpdir);
307 | // Moving the eavesdrop tool binary to /usr/bin
308 | const dest = `${into}${this.name}`;
309 | core.info(`moving ${this.name} to ${path.dirname(dest)}`);
310 | const code = await exec.exec('sudo', ['mv', location, dest]);
311 | if (code !== 0) {
312 | throw new Error(
313 | `couldn't move ${this.name} to ${path.dirname(dest)}`
314 | );
315 | }
316 | this.installed = true;
317 | store(this);
318 |
319 | return dest;
320 | }
321 | );
322 | }
323 |
324 | public async isActive() {
325 | if (!EavesdropMustRun || !this.installed) {
326 | return false;
327 | }
328 |
329 | const res = await core.group(
330 | 'Check whether the CI eavesdrop tool is active',
331 | async (): Promise => {
332 | return await exec.exec('sudo', ['systemctl', 'is-active', this.name], {
333 | ignoreReturnCode: true
334 | });
335 | }
336 | );
337 |
338 | return res === 0;
339 | }
340 |
341 | private async needsRealod() {
342 | return await core.group(
343 | 'Check whether the CI eavesdrop tool needs reload',
344 | async (): Promise => {
345 | const opts: exec.ExecOptions = {
346 | ignoreReturnCode: true
347 | };
348 |
349 | const {stderr, stdout, exitCode} = await exec.getExecOutput(
350 | 'sudo',
351 | ['systemctl', 'show', this.name, '--property=NeedDaemonReload'],
352 | opts
353 | );
354 |
355 | if (exitCode !== 0) {
356 | core.warning(stderr);
357 |
358 | return false;
359 | }
360 |
361 | return stdout.trim().endsWith('=yes');
362 | }
363 | );
364 | }
365 |
366 | public async stop() {
367 | if (!EavesdropMustRun || !this.installed) {
368 | return 0; // Nothing to stop
369 | }
370 |
371 | const needsReload = await this.needsRealod();
372 | if (needsReload) {
373 | await daemonsReload();
374 | }
375 |
376 | return await core.group(
377 | 'Stopping the CI eavesdrop tool',
378 | async (): Promise => {
379 | return await exec.exec('sudo', ['systemctl', 'stop', this.name]);
380 | }
381 | );
382 | }
383 |
384 | public async classifyEnvironmentFile() {
385 | if (!EavesdropMustRun || !this.installed) {
386 | return true;
387 | }
388 |
389 | const {exists, content} = await this.getEnvironmentFile();
390 | if (!exists) {
391 | return false;
392 | }
393 | if (content.length == 0) {
394 | return false;
395 | }
396 | const lines = content.split('\n');
397 |
398 | const secrets = new Set(['OPENAI_TOKEN']);
399 |
400 | for (const line of lines) {
401 | const l = line.trim();
402 | if (!l || l.startsWith('#')) continue;
403 |
404 | const match = l.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/);
405 | if (match) {
406 | const name = match[1].trim();
407 | let value = match[2].trim();
408 |
409 | // Handle quoted values
410 | if (value.startsWith('"') && value.endsWith('"')) {
411 | // Remove quotes and handle escaped quotes
412 | value = value.slice(1, -1).replace(/\\"/g, '"');
413 | } else if (value.startsWith("'") && value.endsWith("'")) {
414 | // Remove quotes and handle escaped quotes
415 | value = value.slice(1, -1).replace(/\\'/g, "'");
416 | }
417 |
418 | if (secrets.has(name)) {
419 | core.setSecret(value);
420 | }
421 | }
422 | }
423 |
424 | return true;
425 | }
426 | }
427 |
428 | const s = new Serializer({classes: {Tool}});
429 |
430 | function deserialize(data: string): Tool {
431 | return s.deserialize(data);
432 | }
433 |
434 | function store(instance: Tool) {
435 | core.saveState(STATE_ID, instance.serialize());
436 | }
437 |
438 | export function get(): Tool {
439 | if (!state.IsPost) {
440 | try {
441 | const i = new Tool();
442 | store(i);
443 |
444 | return i;
445 | } catch (error: any) {
446 | core.setFailed(`Could not instantiate the eavesdrop tool.`);
447 | throw error;
448 | }
449 | }
450 |
451 | try {
452 | return deserialize(core.getState(STATE_ID));
453 | } catch (error: any) {
454 | throw new Error(`Could not deserialize the eavesdrop tool instance.`);
455 | }
456 | }
457 |
--------------------------------------------------------------------------------
/src/flags.ts:
--------------------------------------------------------------------------------
1 | export function parse(flags: string): string[] {
2 | flags = flags.trim();
3 | // (?= # Beginning of a positive lookahead
4 | // ( # Beginning of the first capturing group
5 | // -(?:-\w+|\w)(?:=| ) # Matches a flag name (a dash followed by a single char or two dashes follower by a word) followed by an equal sign or a space
6 | // ) # End of the first capturing group
7 | // ) # End of the positive lookahead
8 | // \1 # Backreference to the first capturing group to match the flag name followed by an equal sign or by a space
9 | // | # Or
10 | // "" # Matches an empty double quote
11 | // | # Or
12 | // '' # Matches an empty single quote
13 | // | # Or
14 | // (["']) # A capturing group (the second one) matching the opening quote (either both or single)
15 | // [^]* # Matches any character (including newlines) or or more times
16 | // [^\\] # Matches the last character preceeding the ending quote that is not a backslash
17 | // (?:\\\\)* # Matches only if the number of backslashes is a multiple of 2 (including zero) so that escaped backslashes are not counted
18 | // \2 # Backreference to match the same opening quote
19 | // | # Or
20 | // [^ "']+ # Matches any character without quotes or spaces one or more times (flag values without quotes)
21 | const parts = flags
22 | .match(
23 | /(?=(-(?:-\w+|\w)(?:=| )))\1|""|''|(["'])[^]*?[^\\](?:\\\\)*\2|[^ "']+/g
24 | )
25 | // Removing matching quotes
26 | ?.map(arg => arg.replace(/^"(.*)"$/, '$1'))
27 | ?.map(arg => arg.replace(/^'(.*)'$/, '$1'))
28 | // Removing trailing equal sign or trailing space from parts starting with a dash
29 | ?.map(arg => arg.replace(/^-(.*)(=| )$/, '-$1'));
30 |
31 | return parts || [];
32 | }
33 |
--------------------------------------------------------------------------------
/src/install.ts:
--------------------------------------------------------------------------------
1 | import * as core from '@actions/core';
2 | import * as http from '@actions/http-client';
3 |
4 | // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
5 | const packageJSON = require('../package.json');
6 |
7 | export function getPlat(os: string): string {
8 | os = os.trim().toLowerCase();
9 |
10 | if (
11 | os.startsWith('win') ||
12 | os.startsWith('cygwin') ||
13 | os.startsWith('mingw') ||
14 | os.startsWith('msys')
15 | ) {
16 | os = 'windows';
17 | }
18 |
19 | if (os.startsWith('darwin')) {
20 | os = 'macos';
21 | }
22 |
23 | switch (os) {
24 | case 'macos':
25 | break;
26 | case 'linux':
27 | break;
28 | default:
29 | throw new Error(`unsupported platform: ${os}`);
30 | }
31 |
32 | return os;
33 | }
34 |
35 | export function getArch(arch: string): string {
36 | arch = arch.trim().toLowerCase();
37 |
38 | switch (arch) {
39 | case 'x64':
40 | arch = 'amd64';
41 | break;
42 | case 'x32':
43 | arch = '386';
44 | break;
45 | case 'arm64':
46 | break;
47 | case 'armv6':
48 | break;
49 | default:
50 | throw new Error(`unsupported arch: ${arch}`);
51 | }
52 |
53 | return arch;
54 | }
55 |
56 | export function getFormat(platform: string): string {
57 | if (platform == 'windows') {
58 | return 'zip';
59 | }
60 | return 'tar.gz';
61 | }
62 |
63 | export async function tagToVersion(
64 | tag: string,
65 | owner: string,
66 | repo: string
67 | ): Promise {
68 | core.info(`looking for ${repo}/${tag}`);
69 |
70 | interface Release {
71 | tag_name: string;
72 | }
73 |
74 | const version =
75 | process.env.npm_package_version || packageJSON.version || 'unknown';
76 | const ua = `listendev-action/${version}; ${repo}/${tag}`;
77 | const url = `https://github.com/${owner}/${repo}/releases/${tag}`;
78 | const client = new http.HttpClient(ua);
79 | const headers = {[http.Headers.Accept]: 'application/json'};
80 | const response = await client.getJson(url, headers);
81 |
82 | core.info(`looking for release ${url}`);
83 | core.info(`using user agent "${ua}"`);
84 |
85 | if (response.statusCode != http.HttpCodes.OK) {
86 | core.error(
87 | `${url} returns unexpected HTTP status code: ${response.statusCode}`
88 | );
89 | }
90 | if (!response.result) {
91 | throw new Error(
92 | `unable to find '${tag}': use 'latest' or see https://github.com/${owner}/${repo}/releases for details`
93 | );
94 | }
95 | let realTag = response.result.tag_name;
96 |
97 | // if version starts with 'v', remove it
98 | realTag = realTag.replace(/^v/, '');
99 |
100 | return realTag;
101 | }
102 |
--------------------------------------------------------------------------------
/src/lstn.ts:
--------------------------------------------------------------------------------
1 | import {Serializer, toSerialize, toDeserialize} from 'superserial';
2 | import * as state from './state';
3 | import * as core from '@actions/core';
4 | import {EavesdropMustRun, EavesdropMustRunAlone} from './constants';
5 | import {getArch, getFormat, getPlat, tagToVersion} from './install';
6 | import * as tc from '@actions/tool-cache';
7 | import * as path from 'path';
8 | import * as exec from '@actions/exec';
9 | import * as flags from './flags';
10 | import {Tool as Eavesdrop} from './eavesdrop';
11 | import * as semver from 'semver';
12 | import axios, {AxiosResponse} from 'axios';
13 | import {Octokit} from '@octokit/rest';
14 | import fs from 'fs';
15 |
16 | const STATE_ID = 'lstn';
17 |
18 | export class Tool {
19 | private version: string;
20 | private jwt: string;
21 | private path = '';
22 | private command: string;
23 | private args: string[];
24 | private cwd: string;
25 | private extraFlags: string[];
26 |
27 | serialize() {
28 | return s.serialize(this);
29 | }
30 |
31 | [toSerialize]() {
32 | return {
33 | version: this.version,
34 | jwt: this.jwt,
35 | path: this.path,
36 | command: this.command,
37 | args: this.args,
38 | cwd: this.cwd,
39 | extraFlags: this.extraFlags
40 | };
41 | }
42 |
43 | [toDeserialize](value: {
44 | version: string;
45 | jwt: string;
46 | path: string;
47 | command: string;
48 | args: string[];
49 | cwd: string;
50 | extraFlags: string[];
51 | }) {
52 | this.version = value.version;
53 | this.jwt = value.jwt;
54 | this.path = value.path;
55 | this.command = value.command;
56 | this.args = value.args;
57 | this.cwd = value.cwd;
58 | this.extraFlags = value.extraFlags;
59 | }
60 |
61 | constructor() {
62 | const versions = Object.keys(Eavesdrop.tagMap);
63 | const v = core.getInput('lstn');
64 | this.version = v == 'latest' ? versions[0] : v;
65 |
66 | this.jwt = core.getInput('jwt', {required: EavesdropMustRun});
67 |
68 | this.command = this.jwt !== '' ? 'in' : 'scan';
69 |
70 | const reporter = core.getInput('reporter');
71 | const select = core.getInput('select');
72 | this.args = ['--reporter', `${this.jwt != '' ? 'pro' : reporter}`]; // There's always a reporter (default)
73 | if (select != '') {
74 | this.args.push(...['--select', `${select}`]);
75 | }
76 |
77 | this.cwd = path.relative(
78 | process.env['GITHUB_WORKSPACE'] || process.cwd(),
79 | core.getInput('workdir')
80 | );
81 |
82 | // The `lstn_flags` option is only meant for expert users and tests.
83 | this.extraFlags = flags.parse(core.getInput('lstn_flags'));
84 | }
85 |
86 | public setConfig(file: string) {
87 | this.args.push(...['--config', file]);
88 | store(this);
89 | }
90 |
91 | public isInstalled(): boolean {
92 | return this.path !== '';
93 | }
94 |
95 | public getVersion(): string {
96 | return this.version;
97 | }
98 |
99 | // It returns the URL to download the LSTN CLI based on the parameter value `lstn`.
100 | // In `dev` mode it will pick the latest release from the `listendev/lstn-dev` repository.
101 | // Otherwise, it will use the public CLI from the `listendev/lstn` repository.
102 | private async buildURL() {
103 | const v = core.getInput('lstn');
104 | if (v == 'dev') {
105 | return 'https://github.com/listendev/lstn-dev/releases/download/v0.0.0/lstn_0.0.0_linux_amd64.tar.gz';
106 | }
107 |
108 | const owner = 'listendev';
109 | const repo = 'lstn';
110 | const vers = await tagToVersion(this.version, owner, repo);
111 | const plat = getPlat(process.platform.toString());
112 | const arch = getArch(process.arch.toString());
113 | const archive = getFormat(plat);
114 | const name = `lstn_${vers}_${plat}_${arch}`;
115 | const url = `https://github.com/${owner}/${repo}/releases/download/v${vers}/${name}.${archive}`;
116 |
117 | return url;
118 | }
119 |
120 | public async install(tmpdir: string) {
121 | const where = await core.group(
122 | '🐬 Installing lstn... https://github.com/listendev/lstn',
123 | async () => {
124 | const v = core.getInput('lstn');
125 | core.info(`Installing version ${v}...`);
126 | const repo = 'lstn';
127 | const owner = 'listendev';
128 | const vers =
129 | v === 'dev' ? '0.0.0' : await tagToVersion(this.version, owner, repo);
130 |
131 | const plat = getPlat(process.platform.toString());
132 | const arch = getArch(process.arch.toString());
133 | const archive = getFormat(plat);
134 |
135 | const url = await this.buildURL();
136 | core.info(`Downloading from ${url}`);
137 |
138 | let download = '';
139 |
140 | if (v === 'dev') {
141 | const token = process.env['pat_pvt_repo'];
142 | if (!token) {
143 | core.warning('Missing private repo PAT');
144 | }
145 |
146 | const octokit = new Octokit({
147 | auth: token
148 | });
149 |
150 | try {
151 | // Request list of assets for release v0.0.0
152 | const res = await octokit.rest.repos.getReleaseByTag({
153 | owner: 'listendev',
154 | repo: 'lstn-dev',
155 | tag: 'v0.0.0'
156 | });
157 |
158 | // Find asset id for lstn_0.0.0_linux_amd64.tar.gz
159 | let asset_id = 0;
160 | const name = 'lstn_0.0.0_linux_amd64.tar.gz';
161 | for (const asset of res.data.assets) {
162 | if (asset.name === name) {
163 | asset_id = asset.id;
164 | break;
165 | }
166 | }
167 |
168 | if (asset_id === 0) {
169 | core.warning(
170 | 'Could not find asset id for lstn_0.0.0_linux_amd64.tar.gz'
171 | );
172 |
173 | throw new Error(
174 | 'Could not find asset id for lstn_0.0.0_linux_amd64.tar.gz'
175 | );
176 | }
177 |
178 | // Find URL to download asset
179 | const resp = await octokit.rest.repos.getReleaseAsset({
180 | owner: 'listendev',
181 | repo: 'lstn-dev',
182 | asset_id: asset_id,
183 | headers: {
184 | Accept: 'application/octet-stream'
185 | }
186 | });
187 |
188 | // Start downloading the asset (wrap in Promise)
189 | const downloadUrl = resp.url;
190 | const filePath = path.resolve(__dirname, name);
191 | const writer = fs.createWriteStream(filePath);
192 |
193 | download = await new Promise((resolve, reject) => {
194 | // Use axios to download the file
195 | axios({
196 | method: 'get',
197 | url: downloadUrl,
198 | responseType: 'stream'
199 | })
200 | .then((downloadResponse: AxiosResponse) => {
201 | downloadResponse.data.pipe(writer);
202 |
203 | writer.on('finish', () => {
204 | core.info(`Download completed: ${filePath}`);
205 | resolve(filePath); // Resolve the Promise when the download is complete
206 | });
207 |
208 | writer.on('error', (e: any) => {
209 | core.warning('Error downloading file:', e);
210 | reject(e); // Reject the Promise if there's an error
211 | });
212 | })
213 | .catch((error: any) => {
214 | core.warning('Error downloading file with axios:', error);
215 | reject(error); // Reject if axios request fails
216 | });
217 | });
218 | } catch {
219 | core.error('Error downloading file');
220 | throw new Error('Error downloading file');
221 | }
222 | } else {
223 | try {
224 | download = await tc.downloadTool(url);
225 | core.info(`Download completed: ${download}`);
226 | } catch (error) {
227 | core.error(`Error downloading file: ${error}`);
228 | throw error;
229 | }
230 | }
231 |
232 | core.info(`Extracting ${download}...`);
233 |
234 | let res = '';
235 | try {
236 | if (archive === 'zip') {
237 | res = await tc.extractZip(download, tmpdir);
238 | } else {
239 | res = await tc.extractTar(download, tmpdir);
240 | }
241 | } catch (error) {
242 | core.error(`Error extracting archive: ${error}`);
243 | throw error;
244 | }
245 |
246 | const name = `lstn_${vers}_${plat}_${arch}`;
247 | const extractedPath = path.join(
248 | res,
249 | name,
250 | `lstn${archive === 'zip' ? '.exe' : ''}`
251 | );
252 | return extractedPath;
253 | }
254 | );
255 |
256 | this.path = where;
257 | store(this);
258 |
259 | return where;
260 | }
261 |
262 | public async exec() {
263 | if (EavesdropMustRunAlone || !this.isInstalled()) {
264 | return 0;
265 | }
266 |
267 | this.setEnv();
268 |
269 | return await exec.exec(
270 | this.path,
271 | [this.command, ...this.args, ...this.extraFlags],
272 | {
273 | cwd: this.cwd
274 | // TODO: ignoreReturnCode
275 | // TODO: outStream
276 | }
277 | );
278 | }
279 |
280 | public async report() {
281 | if (!EavesdropMustRun) {
282 | return 0;
283 | }
284 |
285 | if (!this.isInstalled()) {
286 | core.warning('missing lstn CLI installation');
287 | return 0;
288 | }
289 |
290 | // Check CLI version >= 0.16.0
291 | const version = semver.coerce(this.version);
292 | if (this.version !== 'dev') {
293 | if (!version || !semver.valid(version)) {
294 | throw new Error(`invalid lstn version (${this.version})`);
295 | }
296 | if (semver.lt(version, 'v0.16.0')) {
297 | core.warning(
298 | `Coulnd't report because lstn ${this.version} lacks this ability`
299 | );
300 | return 0;
301 | }
302 | }
303 |
304 | this.setEnv();
305 |
306 | const res = await core.group(
307 | 'Report runtime threats if possible',
308 | async (): Promise => {
309 | return await exec.exec(this.path, ['ci', 'report']);
310 | }
311 | );
312 |
313 | return res;
314 | }
315 |
316 | public async eavesdrop(eavesdrop: Eavesdrop) {
317 | if (!EavesdropMustRun) {
318 | return 0;
319 | }
320 |
321 | if (!this.isInstalled()) {
322 | core.warning('missing lstn CLI installation');
323 | return 0;
324 | }
325 |
326 | this.setEnv();
327 |
328 | const exit = await exec.exec('sudo', [
329 | '-E',
330 | this.path,
331 | ...eavesdrop.getCliEnablingCommand(),
332 | ...this.extraFlags
333 | ]);
334 |
335 | if (exit === 0) {
336 | const didClassify = await eavesdrop.classifyEnvironmentFile();
337 | if (!didClassify) {
338 | core.warning(
339 | "couldn't classify the CI eavesdrop configuration variables"
340 | );
341 | }
342 | }
343 |
344 | return exit;
345 | }
346 |
347 | private setEnv() {
348 | // Pass tokens down
349 | process.env['LSTN_GH_TOKEN'] = core.getInput('token');
350 | process.env['LSTN_JWT_TOKEN'] = this.jwt;
351 | // Ensure $PATH contains /usr/bin
352 | process.env['PATH'] = !process.env['PATH']
353 | ? '/usr/bin'
354 | : `${process.env['PATH']}:/usr/bin`;
355 | }
356 | }
357 |
358 | const s = new Serializer({classes: {Tool}});
359 |
360 | function deserialize(data: string): Tool {
361 | return s.deserialize(data);
362 | }
363 |
364 | function store(instance: Tool) {
365 | core.saveState(STATE_ID, instance.serialize());
366 | }
367 |
368 | export function get(): Tool {
369 | if (!state.IsPost) {
370 | try {
371 | const i = new Tool();
372 | store(i);
373 |
374 | return i;
375 | } catch (error: any) {
376 | core.setFailed(`Could not instantiate the lstn tool.`);
377 | throw error;
378 | }
379 | }
380 |
381 | try {
382 | return deserialize(core.getState(STATE_ID));
383 | } catch (error: any) {
384 | throw new Error(`Could not deserialize the lstn tool instance.`);
385 | }
386 | }
387 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import * as core from '@actions/core';
2 | import * as utils from './utils';
3 | import * as state from './state';
4 | import * as eavesdropcli from './eavesdrop';
5 | import * as lstncli from './lstn';
6 | import {EavesdropMustRun, EavesdropMustRunAlone} from './constants';
7 | import * as path from 'path';
8 | import * as io from '@actions/io';
9 |
10 | async function run() {
11 | const tmpdir = await state.tmpdir();
12 | try {
13 | const lstn = lstncli.get();
14 | await lstn.install(tmpdir);
15 |
16 | const eavesdrop = eavesdropcli.get();
17 | await eavesdrop.install(tmpdir);
18 |
19 | // TODO: restore cache here
20 |
21 | // Handle lstn config
22 | const config = core.getInput('config');
23 | if (config != '') {
24 | const res = await utils.checkPath(config);
25 | if (!res.exists) {
26 | core.setFailed(`${config} does not exists`);
27 |
28 | return;
29 | }
30 | if (res.isFile) {
31 | lstn.setConfig(config);
32 | } else {
33 | // The input config is a directory
34 | const defaultFile = path.join(config, '.lstn.yaml');
35 | const fallback = await utils.checkPath(defaultFile);
36 | if (!fallback.exists) {
37 | core.setFailed(`${defaultFile} config file does not exists`);
38 |
39 | return;
40 | }
41 | // Assuming that defaultFile is a proper file now
42 | lstn.setConfig(defaultFile);
43 | }
44 | }
45 |
46 | const exit = await core.group(
47 | `🐬 Running lstn${EavesdropMustRun ? ' with CI eavesdropper' : '...'}${
48 | EavesdropMustRunAlone ? ' only' : ''
49 | }`,
50 | async (): Promise => {
51 | // TODO: what to do when status code != 0
52 | let code = await lstn.eavesdrop(eavesdrop);
53 | code = await lstn.exec();
54 |
55 | return code;
56 | }
57 | );
58 |
59 | // TODO: save cache here
60 |
61 | if (exit !== 0) {
62 | core.setFailed(`status code: ${exit}`);
63 | }
64 | } catch (error: any) {
65 | core.setFailed(error);
66 | }
67 | }
68 |
69 | async function post() {
70 | const tmpdir = await state.tmpdir();
71 | try {
72 | const eavesdrop = eavesdropcli.get();
73 | const isActive = await eavesdrop.isActive();
74 | if (!isActive) {
75 | core.info(`Moving on since the CI eavesdrop tool isn't active`);
76 |
77 | return;
78 | }
79 |
80 | const exit = await eavesdrop.stop();
81 | if (exit !== 0) {
82 | core.warning(`Couldn't properly stop the CI eavesdrop tool`);
83 | }
84 |
85 | const lstn = lstncli.get();
86 | const reportExitCode = await lstn.report();
87 | if (reportExitCode !== 0) {
88 | core.warning(`Couldn't comment on the pull request`);
89 | }
90 | } catch (error: any) {
91 | core.setFailed(error);
92 | } finally {
93 | // Cleanup
94 | try {
95 | core.info('Cleaning up');
96 | await io.rmRF(tmpdir);
97 | } catch (error) {
98 | // Suppress these errors
99 | if (error instanceof Error) {
100 | core.warning(`Couldn't clean up: ${error.message}`);
101 | } else {
102 | core.warning(`Couldn't clean up: ${error}`);
103 | }
104 | }
105 | }
106 | }
107 |
108 | if (!state.IsPost) {
109 | run();
110 | } else {
111 | post();
112 | }
113 |
--------------------------------------------------------------------------------
/src/state.ts:
--------------------------------------------------------------------------------
1 | import * as core from '@actions/core';
2 | import * as os from 'os';
3 | import {promises as fs} from 'fs';
4 | import * as path from 'path';
5 |
6 | /**
7 | * Indicates whether the POST action is running
8 | */
9 | export const IsPost = !!core.getState('isPost');
10 |
11 | // Publish a variable so that when the POST action runs, it can determine it should run the cleanup logic.
12 | // This is necessary since we don't have a separate entry point.
13 | if (!IsPost) {
14 | core.saveState('isPost', 'true');
15 | }
16 |
17 | export async function tmpdir() {
18 | if (!IsPost) {
19 | const tmpdir = await fs.mkdtemp(
20 | path.join(process.env['RUNNER_TEMP'] || os.tmpdir(), 'lstn-')
21 | );
22 | core.saveState('LSTN_ACTION_TMPDIR', tmpdir);
23 |
24 | return tmpdir;
25 | }
26 |
27 | return core.getState('LSTN_ACTION_TMPDIR');
28 | }
29 |
--------------------------------------------------------------------------------
/src/systemctl.ts:
--------------------------------------------------------------------------------
1 | import * as core from '@actions/core';
2 | import * as exec from '@actions/exec';
3 |
4 | export async function daemonsReload() {
5 | return await core.group('Reload daemons', async (): Promise => {
6 | const opts: exec.ExecOptions = {
7 | ignoreReturnCode: true
8 | };
9 |
10 | const {stderr, exitCode} = await exec.getExecOutput(
11 | 'sudo',
12 | ['systemctl', 'daemon-reload'],
13 | opts
14 | );
15 |
16 | if (exitCode !== 0) {
17 | // Handle error case, you can log stderr or throw an error
18 | core.warning(stderr);
19 | } else {
20 | core.info('Successfull reload');
21 | }
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | import {PathLike, promises as fs} from 'fs';
2 | import * as exec from '@actions/exec';
3 |
4 | export async function checkPath(path: PathLike, withSudo = false) {
5 | try {
6 | if (withSudo) {
7 | let isFile = false;
8 | const opts: exec.ExecOptions = {
9 | silent: true,
10 | ignoreReturnCode: true,
11 | listeners: {
12 | stdout: (data: Buffer) => {
13 | const res = data.toString().trim();
14 | isFile = res.startsWith('-') || res.includes('File:');
15 | }
16 | }
17 | };
18 |
19 | const exit = await exec.exec('sudo', ['stat', path.toString()], opts);
20 | if (exit !== 0) {
21 | return {exists: false};
22 | }
23 |
24 | return {exists: true, isFile: isFile};
25 | } else {
26 | const stats = await fs.stat(path);
27 | if (stats.isFile()) {
28 | return {exists: true, isFile: true};
29 | } else if (stats.isDirectory()) {
30 | return {exists: true, isFile: false};
31 | } else {
32 | // Handle other types (unlikely in most cases)
33 | return {exists: true, isFile: undefined};
34 | }
35 | }
36 | } catch (error: any) {
37 | if (error.code === 'ENOENT') {
38 | return {exists: false};
39 | } else if (error.code === 'EACCES') {
40 | return {exists: false};
41 | } else {
42 | throw error; // Re-throw other errors
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2021", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
4 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
5 | "outDir": "./lib", /* Redirect output structure to the directory. */
6 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
7 | "strict": true, /* Enable all strict type-checking options. */
8 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
9 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
10 | "resolveJsonModule": true,
11 | "moduleResolution": "node"
12 | },
13 | "exclude": ["node_modules", "__tests__/*.test.ts", "lib"],
14 | "files": [
15 | "node_modules/jest-os-detection/index.d.ts"
16 | ]
17 | }
--------------------------------------------------------------------------------