Compare commits

...

19 commits
v9.0.0 ... main

Author SHA1 Message Date
dependabot[bot]
ca80beefdd
build(deps-dev): bump the dev-dependencies group with 3 updates (#1325)
Some checks failed
build-and-test / test (macos-latest, v2.7.2) (push) Has been cancelled
build-and-test / test (ubuntu-22.04-arm, ) (push) Has been cancelled
build-and-test / test (ubuntu-22.04-arm, latest) (push) Has been cancelled
build-and-test / test (ubuntu-22.04-arm, v2.7) (push) Has been cancelled
build-and-test / test (ubuntu-22.04-arm, v2.7.2) (push) Has been cancelled
build-and-test / test (ubuntu-latest, ) (push) Has been cancelled
build-and-test / test (ubuntu-latest, latest) (push) Has been cancelled
build-and-test / test (ubuntu-latest, v2.7) (push) Has been cancelled
build-and-test / test (ubuntu-latest, v2.7.2) (push) Has been cancelled
build-and-test / test (windows-latest, ) (push) Has been cancelled
build-and-test / test (windows-latest, latest) (push) Has been cancelled
build-and-test / test (windows-latest, v2.7) (push) Has been cancelled
build-and-test / test (windows-latest, v2.7.2) (push) Has been cancelled
build-and-test / test-go-install (macos-latest, ) (push) Has been cancelled
build-and-test / test-go-install (macos-latest, 655e8ede5178280b2a640e185bc4a343aed0f54e) (push) Has been cancelled
build-and-test / test-go-install (macos-latest, latest) (push) Has been cancelled
build-and-test / test-go-install (macos-latest, v2.7.2) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-22.04-arm, ) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-22.04-arm, 655e8ede5178280b2a640e185bc4a343aed0f54e) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-22.04-arm, latest) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-22.04-arm, v2.7.2) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-latest, ) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-latest, 655e8ede5178280b2a640e185bc4a343aed0f54e) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-latest, latest) (push) Has been cancelled
build-and-test / test-go-install (ubuntu-latest, v2.7.2) (push) Has been cancelled
build-and-test / test-go-install (windows-latest, ) (push) Has been cancelled
build-and-test / test-go-install (windows-latest, 655e8ede5178280b2a640e185bc4a343aed0f54e) (push) Has been cancelled
build-and-test / test-go-install (windows-latest, latest) (push) Has been cancelled
build-and-test / test-go-install (windows-latest, v2.7.2) (push) Has been cancelled
build-and-test / test-go-mod (macos-latest, fixtures/go-mod) (push) Has been cancelled
2025-12-08 13:32:43 +01:00
Fernandez Ludovic
87a373f691
chore: update workflow 2025-12-08 13:12:37 +01:00
Fernandez Ludovic
7fa6da85a5
chore: update workflow
Some checks are pending
build-and-test / test-go-install (windows-latest, 655e8ede5178280b2a640e185bc4a343aed0f54e) (push) Blocked by required conditions
build-and-test / test-go-install (windows-latest, latest) (push) Blocked by required conditions
build-and-test / test-go-install (windows-latest, v2.7.0) (push) Blocked by required conditions
build-and-test / test-go-mod (macos-latest, fixtures/go-mod) (push) Blocked by required conditions
build-and-test / test-go-mod (macos-latest, fixtures/go-tool) (push) Blocked by required conditions
build-and-test / test-go-mod (ubuntu-22.04-arm, fixtures/go-tool) (push) Blocked by required conditions
build-and-test / test-go-mod (ubuntu-latest, fixtures/go-mod) (push) Blocked by required conditions
build-and-test / test-go-mod (ubuntu-latest, fixtures/go-tool) (push) Blocked by required conditions
build-and-test / test-go-mod (windows-latest, fixtures/go-mod) (push) Blocked by required conditions
build-and-test / test-go-mod (windows-latest, fixtures/go-tool) (push) Blocked by required conditions
build-and-test / test-plugins (macos-latest, ) (push) Blocked by required conditions
build-and-test / test-plugins (macos-latest, latest) (push) Blocked by required conditions
build-and-test / test-plugins (macos-latest, v2.7) (push) Blocked by required conditions
build-and-test / test-plugins (macos-latest, v2.7.1) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-22.04-arm, ) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-22.04-arm, latest) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-22.04-arm, v2.7) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-22.04-arm, v2.7.1) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-latest, ) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-latest, latest) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-latest, v2.7) (push) Blocked by required conditions
build-and-test / test-plugins (ubuntu-latest, v2.7.1) (push) Blocked by required conditions
build-and-test / test-plugins (windows-latest, ) (push) Blocked by required conditions
build-and-test / test-plugins (windows-latest, latest) (push) Blocked by required conditions
build-and-test / test-plugins (windows-latest, v2.7) (push) Blocked by required conditions
build-and-test / test-plugins (windows-latest, v2.7.1) (push) Blocked by required conditions
build-and-test / test-monorepo (macos-latest) (push) Blocked by required conditions
build-and-test / test-monorepo (ubuntu-22.04-arm) (push) Blocked by required conditions
build-and-test / test-monorepo (ubuntu-latest) (push) Blocked by required conditions
build-and-test / test-monorepo (windows-latest) (push) Blocked by required conditions
2025-12-08 12:54:19 +01:00
dependabot[bot]
1e7e51e771
build(deps): bump yaml from 2.8.1 to 2.8.2 in the dependencies group (#1324)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
2025-12-01 13:01:48 +01:00
dependabot[bot]
5256ff0c0a
build(deps-dev): bump the dev-dependencies group with 3 updates (#1323) 2025-12-01 12:32:33 +01:00
Fernandez Ludovic
13fed6f911 chore: update workflows 2025-11-28 17:39:49 +01:00
Fernandez Ludovic
7afe8ff863 chore: update workflows 2025-11-28 17:28:27 +01:00
Ludovic Fernandez
5a9289952f
chore: move samples into fixtures (#1321) 2025-11-28 17:21:09 +01:00
Ludovic Fernandez
aa6fad0ea0
feat: add version-file option (#1320) 2025-11-28 16:54:48 +01:00
dependabot[bot]
a6071aaacb
build(deps): bump actions/checkout from 5 to 6 (#1318) 2025-11-24 12:36:51 +01:00
dependabot[bot]
6e36c8460f
build(deps-dev): bump the dev-dependencies group with 2 updates (#1317) 2025-11-24 12:36:23 +01:00
Ludovic Fernandez
e7fa5ac41e
feat: automatic module directories (#1315) 2025-11-21 16:03:27 +01:00
Ludovic Fernandez
f3ae99f5f5
docs: organize options (#1314) 2025-11-21 15:52:17 +01:00
Fernandez Ludovic
1dfda283ac
docs: update readme 2025-11-18 18:51:26 +01:00
dependabot[bot]
8b0f9424d0
build(deps): bump the dependencies group with 2 updates (#1311) 2025-11-17 13:18:39 +01:00
dependabot[bot]
a77756c838
build(deps-dev): bump the dev-dependencies group with 2 updates (#1310) 2025-11-17 13:18:04 +01:00
dependabot[bot]
37a9fafcae
build(deps-dev): bump js-yaml from 4.1.0 to 4.1.1 (#1309) 2025-11-15 13:23:43 +01:00
dependabot[bot]
199a9c2889
build(deps-dev): bump the dev-dependencies group with 2 updates (#1307) 2025-11-10 11:00:55 +01:00
Fernandez Ludovic
c7c1219093
chore: simplify 2025-11-09 10:04:50 +01:00
38 changed files with 970 additions and 610 deletions

View file

@ -11,6 +11,11 @@ on:
schedule:
- cron: '0 17 * * 5'
permissions:
actions: read
contents: read
security-events: write
jobs:
codeQL:
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
@ -18,7 +23,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
# Must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head of the pull request.
@ -36,7 +41,7 @@ jobs:
uses: github/codeql-action/init@v4
# Override language selection by uncommenting this and choosing your languages
with:
language: 'javascript'
languages: 'javascript-typescript'
- run: |
npm install

View file

@ -1,5 +1,6 @@
name: "build-and-test"
on: # rebuild any PRs and main branch changes
on:
pull_request:
branches:
- main
@ -7,22 +8,27 @@ on: # rebuild any PRs and main branch changes
branches:
- main
permissions:
contents: read
jobs:
build: # make sure build/ci work properly
# make sure build/ci work properly
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v6
with:
node-version: 24.x
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- run: |
npm install
npm run all
# Fail the build if there is dirty change
# Fail the build if there are changes.
- run: git diff --exit-code -- dist
test: # make sure the action works on a clean machine without building
# make sure the action works on a clean machine without building
test:
needs: [ build ]
strategy:
matrix:
@ -34,14 +40,14 @@ jobs:
version:
- ""
- "latest"
- "v2.5"
- "v2.5.0"
- "v2.7"
- "v2.7.2"
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24.x
@ -51,10 +57,11 @@ jobs:
- uses: ./
with:
version: ${{ matrix.version }}
args: --timeout=5m --issues-exit-code=0 ./sample/...
args: --timeout=5m --issues-exit-code=0 ./fixtures/simple/...
only-new-issues: true
test-go-install: # make sure the action works on a clean machine without building (go-install mode)
# make sure the action works on a clean machine without building (go-install mode)
test-go-install:
needs: [ build ]
strategy:
matrix:
@ -66,14 +73,14 @@ jobs:
version:
- ""
- "latest"
- "v2.5.0"
- "v2.7.2"
- "655e8ede5178280b2a640e185bc4a343aed0f54e"
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24.x
@ -83,7 +90,7 @@ jobs:
- uses: ./
with:
version: ${{ matrix.version }}
args: --timeout=5m --issues-exit-code=0 ./sample/...
args: --timeout=5m --issues-exit-code=0 ./fixtures/simple/...
only-new-issues: true
install-mode: goinstall
@ -97,13 +104,13 @@ jobs:
- macos-latest
- windows-latest
wd:
- sample-go-mod
- sample-go-tool
- fixtures/go-mod
- fixtures/go-tool
runs-on: ${{ matrix.os }}
permissions:
contents: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24.x
@ -115,7 +122,8 @@ jobs:
working-directory: ${{ matrix.wd }}
args: --timeout=5m --issues-exit-code=0 ./...
test-plugins: # make sure the action works on a clean machine with plugins
# make sure the action works on a clean machine with plugins
test-plugins:
needs: [ build ]
strategy:
matrix:
@ -127,14 +135,14 @@ jobs:
version:
- ""
- "latest"
- "v2.5"
- "v2.5.0"
- "v2.7"
- "v2.7.2"
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24.x
@ -144,5 +152,32 @@ jobs:
- uses: ./
with:
version: ${{ matrix.version }}
working-directory: sample-plugins
working-directory: fixtures/plugins
args: --timeout=5m --issues-exit-code=0 ./...
test-monorepo:
needs: [ build ]
strategy:
matrix:
os:
- ubuntu-latest
- ubuntu-22.04-arm
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
permissions:
contents: read
pull-requests: read
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24.x
- uses: actions/setup-go@v6
with:
go-version: oldstable
- uses: ./
with:
working-directory: fixtures/monorepo
experimental: "automatic-module-directories"
args: --timeout=5m --issues-exit-code=0 ./...

258
README.md
View file

@ -54,9 +54,9 @@ jobs:
with:
go-version: stable
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
version: v2.1
version: v2.6
```
</details>
@ -92,9 +92,9 @@ jobs:
with:
go-version: ${{ matrix.go }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
version: v2.1
version: v2.6
```
You will also likely need to add the following `.gitattributes` file to ensure that line endings for Windows builds are properly formatted:
@ -120,7 +120,7 @@ on:
env:
GO_VERSION: stable
GOLANGCI_LINT_VERSION: v2.1
GOLANGCI_LINT_VERSION: v2.6
jobs:
detect-modules:
@ -147,7 +147,7 @@ jobs:
with:
go-version: ${{ env.GO_VERSION }}
- name: golangci-lint ${{ matrix.modules }}
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
version: ${{ env.GOLANGCI_LINT_VERSION }}
working-directory: ${{ matrix.modules }}
@ -179,7 +179,7 @@ jobs:
with:
os: ${{ matrix.os }}
go-version: ${{ matrix.go-version }}
golangci-lint-version: v2.1
golangci-lint-version: v2.6
```
```yaml
@ -201,7 +201,7 @@ on:
golangci-lint-version:
description: 'Golangci-lint version'
type: string
default: 'v2.1'
default: 'v2.6'
jobs:
detect-modules:
@ -229,7 +229,7 @@ jobs:
with:
go-version: ${{ inputs.go-version }}
- name: golangci-lint ${{ matrix.modules }}
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
version: ${{ inputs.golangci-lint-version }}
working-directory: ${{ matrix.modules }}
@ -259,7 +259,28 @@ You will also likely need to add the following `.gitattributes` file to ensure t
## Options
### `version`
### Overview
| Option | Description |
|---------------------------------------------------------------|-------------------------------------------------------|
| [`version`](#version) | The version of golangci-lint to use. |
| [`version-file`](#version-file) | Gets the version of golangci-lint to use from a file. |
| [`install-mode`](#install-mode) | The mode to install golangci-lint. |
| [`install-only`](#install-only) | Only install golangci-lint. |
| [`verify`](#verify) | Validates golangci-lint configuration file. |
| [`github-token`](#github-token) | Used by the `only-new-issues` option. |
| [`only-new-issues`](#only-new-issues) | Show only new issues. |
| [`working-directory`](#working-directory) | The golangci-lint working directory. |
| [`args`](#args) | Golangci-lint command line arguments. |
| [`skip-cache`](#skip-cache) | Disable cache support. |
| [`skip-save-cache`](#skip-save-cache) | Don't save cache. |
| [`cache-invalidation-interval`](#cache-invalidation-interval) | Number of days before cache invalidation. |
| [`problem-matchers`](#problem-matchers) | Forces the usage of the embedded problem matchers. |
| [Experimental](#experimental) | Experimental options |
### Installation
#### `version`
(optional)
@ -274,15 +295,37 @@ When `install-mode` is:
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
version: v2.1
version: v2.6
# ...
```
</details>
### `install-mode`
#### `version-file`
Gets the version of golangci-lint to use from a file.
The path must be relative to the root of the project, or the `working-directory` if defined.
This parameter supports `.golangci-lint-version`, and `.tool-versions` files.
Only works with `install-mode: binary` (the default).
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v9
with:
version-file: .tool-versions
# ...
```
</details>
#### `install-mode`
(optional)
@ -296,7 +339,7 @@ The default value is `binary`.
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
install-mode: "none"
# ...
@ -304,7 +347,7 @@ with:
</details>
### `install-only`
#### `install-only`
(optional)
@ -317,7 +360,7 @@ The default value is `false`.
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
install-only: true
# ...
@ -325,27 +368,9 @@ with:
</details>
### `github-token`
### Run
(optional)
When using the `only-new-issues` option, the GitHub API is used, so a token is required.
By default, it uses the `github.token` from the action.
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
with:
github-token: xxx
# ...
```
</details>
### `verify`
#### `verify`
(optional)
@ -360,7 +385,7 @@ The JSON Schema used to validate the configuration depends on the version of gol
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
verify: false
# ...
@ -368,7 +393,27 @@ with:
</details>
### `only-new-issues`
#### `github-token`
(optional)
When using the `only-new-issues` option, the GitHub API is used, so a token is required.
By default, it uses the `github.token` from the action.
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v9
with:
github-token: xxx
# ...
```
</details>
#### `only-new-issues`
(optional)
@ -385,7 +430,7 @@ The default value is `false`.
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
only-new-issues: true
# ...
@ -393,7 +438,7 @@ with:
</details>
### `working-directory`
#### `working-directory`
(optional)
@ -403,7 +448,7 @@ The golangci-lint working directory, useful for monorepos. The default is the pr
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
working-directory: somedir
# ...
@ -411,7 +456,7 @@ with:
</details>
### `args`
#### `args`
(optional)
@ -428,7 +473,7 @@ golangci-lint command line arguments.
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
# In some rare cases,
# you may need to use `${{ github.workspace }}` as the base directory to reference your configuration file.
@ -438,7 +483,74 @@ with:
</details>
### `problem-matchers`
### Cache
#### `skip-cache`
(optional)
If set to `true`, all caching functionality will be completely disabled.
This takes precedence over all other caching options.
The default value is `false`.
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v9
with:
skip-cache: true
# ...
```
</details>
#### `skip-save-cache`
(optional)
If set to `true`, caches will not be saved, but they may still be restored, requiring `skip-cache: false`.
The default value is `false`.
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v9
with:
skip-save-cache: true
# ...
```
</details>
#### `cache-invalidation-interval`
(optional)
Periodically invalidate a cache every `cache-invalidation-interval` days to ensure that outdated data is removed and fresh data is loaded.
The default value is `7`.
If the number is `<= 0`, the cache will always be invalidated (not recommended).
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v9
with:
cache-invalidation-interval: 15
# ...
```
</details>
### Extra
#### `problem-matchers`
(optional)
@ -456,7 +568,7 @@ The default value is `false`.
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
uses: golangci/golangci-lint-action@v9
with:
problem-matchers: true
# ...
@ -464,65 +576,43 @@ with:
</details>
### `skip-cache`
### Experimental
(optional)
The following options are experimental: those may or may not be supported in the future, and so they will be either converted into a dedicated option or removed.
If set to `true`, all caching functionality will be completely disabled.
This takes precedence over all other caching options.
The default value is `false`.
List of comma-separated options.
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
```yaml
uses: golangci/golangci-lint-action@v9
with:
skip-cache: true
# ...
experimental: "foo,bar"
```
</details>
### `skip-save-cache`
#### `automatic-module-directories`
(optional)
If set to `true`, caches will not be saved, but they may still be restored, requiring `skip-cache: false`.
This option will run golangci-lint in each module directory, useful for monorepos.
The default value is `false`.
The automatic detection of modules uses the `working-directory` as the base directory if defined, otherwise the root directory.
> [!IMPORTANT]
> - The cache key will refer to the `working-directory` (if defined) because all the golangci-lint runs must use the same cache directory/key.
> - The version detection will only work if the project has a single module.
> - If the project has multiple modules, the custom build file must be located in the repository root ( or `working-directory`).
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
```yaml
uses: golangci/golangci-lint-action@v9
with:
skip-save-cache: true
# ...
```
</details>
### `cache-invalidation-interval`
(optional)
Periodically invalidate a cache every `cache-invalidation-interval` days to ensure that outdated data is removed and fresh data is loaded.
The default value is `7`.
If the number is `<= 0`, the cache will always be invalidated (not recommended).
<details>
<summary>Example</summary>
```yml
uses: golangci/golangci-lint-action@v8
with:
cache-invalidation-interval: 15
# ...
experimental: "automatic-module-directories"
```
</details>

View file

@ -11,6 +11,13 @@ inputs:
- `goinstall`: the value can be v2.3.4, `latest`, or the hash of a commit.
- `none`: the value is ignored.
required: false
version-file:
description: |
Gets the version of golangci-lint to use from a file.
The path must be relative to the root of the project, or the `working-directory` if defined.
This parameter supports `.golangci-lint-version`, and `.tool-versions` files.
Only works with `install-mode: binary` (the default).
required: false
install-mode:
description: "The mode to install golangci-lint. It can be 'binary', 'goinstall', or 'none'."
default: "binary"
@ -34,6 +41,10 @@ inputs:
description: "If set to true and the action runs on a pull request, the action outputs only newly found issues."
default: 'false'
required: false
args:
description: "golangci-lint command line arguments."
default: ""
required: false
skip-cache:
description: |
If set to true, all caching functionality will be completely disabled.
@ -42,21 +53,30 @@ inputs:
required: false
skip-save-cache:
description: |
If set to true, the action will not save any caches, but it may still
restore existing caches, subject to other options.
If set to true, the action will not save any caches,
but it may still restore existing caches, subject to other options.
default: 'false'
required: false
cache-invalidation-interval:
description: "Periodically invalidate a cache when new code is added (number of days)."
default: '7'
required: false
problem-matchers:
description: "Force the usage of the embedded problem matchers."
default: 'false'
required: false
args:
description: "golangci-lint command line arguments."
debug:
description: |
Debug options for the action.
List of comma separated options, the values are `cache`, `clean`.
example: "cache,clean"
default: ""
required: false
cache-invalidation-interval:
description: "Periodically invalidate a cache when new code is added (number of days)."
default: '7'
experimental:
description: |
Experimental options for the action.
List of comma separated options.
default: ""
required: false
runs:
using: "node24"

229
dist/post_run/index.js generated vendored
View file

@ -96844,8 +96844,10 @@ async function buildCacheKeys() {
return keys;
}
async function restoreCache() {
if (core.getBooleanInput(`skip-cache`, { required: true }))
if (core.getBooleanInput(`skip-cache`, { required: true })) {
core.info(`Skipping cache restoration`);
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
return;
@ -96881,10 +96883,14 @@ async function restoreCache() {
}
}
async function saveCache() {
if (core.getBooleanInput(`skip-cache`, { required: true }))
if (core.getBooleanInput(`skip-cache`, { required: true })) {
core.info(`Skipping cache saving`);
return;
if (core.getBooleanInput(`skip-save-cache`, { required: true }))
}
if (core.getBooleanInput(`skip-save-cache`, { required: true })) {
core.info(`Skipping cache saving`);
return;
}
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
@ -96999,12 +97005,13 @@ exports.installBinary = installBinary;
const core = __importStar(__nccwpck_require__(37484));
const tc = __importStar(__nccwpck_require__(33472));
const child_process_1 = __nccwpck_require__(35317);
const fs_1 = __importDefault(__nccwpck_require__(79896));
const os_1 = __importDefault(__nccwpck_require__(70857));
const path_1 = __importDefault(__nccwpck_require__(16928));
const util_1 = __nccwpck_require__(39023);
const which_1 = __importDefault(__nccwpck_require__(11189));
const version_1 = __nccwpck_require__(311);
const execShellCommand = (0, util_1.promisify)(child_process_1.exec);
const execCommand = (0, util_1.promisify)(child_process_1.exec);
var InstallMode;
(function (InstallMode) {
InstallMode["Binary"] = "binary";
@ -97018,6 +97025,7 @@ const printOutput = (res) => {
if (res.stderr) {
core.info(res.stderr);
}
return res;
};
/**
* Install golangci-lint.
@ -97025,6 +97033,15 @@ const printOutput = (res) => {
* @returns path to installed binary of golangci-lint.
*/
async function install() {
const problemMatchers = core.getBooleanInput(`problem-matchers`);
if (problemMatchers) {
const matchersPath = path_1.default.join(__dirname, "../..", "problem-matchers.json");
if (fs_1.default.existsSync(matchersPath)) {
// Adds problem matchers.
// https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83
core.info(`##[add-matcher]${matchersPath}`);
}
}
const mode = core.getInput("install-mode").toLowerCase();
if (mode === InstallMode.None) {
const binPath = await (0, which_1.default)("golangci-lint", { nothrow: true });
@ -97064,10 +97081,8 @@ async function goInstall(versionInfo) {
core.info(`Installing golangci-lint ${versionInfo.TargetVersion}...`);
const startedAt = Date.now();
const options = { env: { ...process.env, CGO_ENABLED: "1" } };
const exres = await execShellCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options);
printOutput(exres);
const res = await execShellCommand(`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options);
printOutput(res);
await execCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then(printOutput);
const res = await execCommand(`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then(printOutput);
// The output of `go install -n` when the binary is already installed is `touch <path_to_the_binary>`.
const binPath = res.stderr
.split(/\r?\n/)
@ -97196,9 +97211,6 @@ function isOnlyNewIssues() {
return core.getBooleanInput(`only-new-issues`, { required: true });
}
async function fetchPatch() {
if (!isOnlyNewIssues()) {
return ``;
}
const ctx = github.context;
switch (ctx.eventName) {
case `pull_request`:
@ -97242,8 +97254,7 @@ async function fetchPullRequestPatch(ctx) {
return ``; // don't fail the action, but analyze without patch
}
try {
const tempDir = await createTempDir();
const patchPath = path_1.default.join(tempDir, "pull.patch");
const patchPath = await createTempDir().then((tempDir) => path_1.default.join(tempDir, "pull.patch"));
core.info(`Writing patch to ${patchPath}`);
await writeFile(patchPath, (0, diffUtils_1.alterDiffPatch)(patch));
return patchPath;
@ -97277,8 +97288,7 @@ async function fetchPushPatch(ctx) {
return ``; // don't fail the action, but analyze without patch
}
try {
const tempDir = await createTempDir();
const patchPath = path_1.default.join(tempDir, "push.patch");
const patchPath = await createTempDir().then((tempDir) => path_1.default.join(tempDir, "push.patch"));
core.info(`Writing patch to ${patchPath}`);
await writeFile(patchPath, (0, diffUtils_1.alterDiffPatch)(patch));
return patchPath;
@ -97341,7 +97351,7 @@ const fs = __importStar(__nccwpck_require__(79896));
const path = __importStar(__nccwpck_require__(16928));
const util_1 = __nccwpck_require__(39023);
const yaml_1 = __importDefault(__nccwpck_require__(38815));
const execShellCommand = (0, util_1.promisify)(child_process_1.exec);
const execCommand = (0, util_1.promisify)(child_process_1.exec);
const printOutput = (res) => {
if (res.stdout) {
core.info(res.stdout);
@ -97361,11 +97371,12 @@ async function install(binPath) {
else {
rootDir = process.cwd();
}
const configFile = [".custom-gcl.yml", ".custom-gcl.yaml", ".custom-gcl.json"]
.map((v) => path.join(rootDir, v))
const configFile = ["yml", "yaml", "json"]
.map((ext) => `.custom-gcl.${ext}`)
.map((filename) => path.join(rootDir, filename))
.find((filePath) => fs.existsSync(filePath));
if (!configFile || configFile === "") {
return "";
return binPath;
}
core.info(`Found configuration for the plugin module system : ${configFile}`);
core.info(`Building and installing custom golangci-lint binary...`);
@ -97373,7 +97384,7 @@ async function install(binPath) {
const config = yaml_1.default.parse(fs.readFileSync(configFile, "utf-8"));
const v = core.getInput(`version`);
if (v !== "" && config.version !== v) {
core.warning(`The golangci-lint version (${config.version}) defined inside in ${configFile} does not match the version defined in the action (${v})`);
core.warning(`The golangci-lint version (${config.version}) defined inside ${configFile} does not match the version defined in the action (${v})`);
}
if (!config.destination) {
config.destination = ".";
@ -97387,18 +97398,16 @@ async function install(binPath) {
}
const cmd = `${binPath} custom`;
core.info(`Running [${cmd}] in [${rootDir}] ...`);
try {
const options = {
cwd: rootDir,
};
const res = await execShellCommand(cmd, options);
printOutput(res);
core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`);
return path.join(rootDir, config.destination, config.name);
}
catch (exc) {
return execCommand(cmd, options)
.then(printOutput)
.then(() => core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`))
.then(() => path.join(rootDir, config.destination, config.name))
.catch((exc) => {
throw new Error(`Failed to build custom golangci-lint binary: ${exc.message}`);
}
});
}
@ -97455,24 +97464,7 @@ const cache_1 = __nccwpck_require__(97377);
const install_1 = __nccwpck_require__(90232);
const patch_1 = __nccwpck_require__(47161);
const plugins = __importStar(__nccwpck_require__(96067));
const execShellCommand = (0, util_1.promisify)(child_process_1.exec);
async function prepareEnv(installOnly) {
const startedAt = Date.now();
// Prepare cache, lint and go in parallel.
await (0, cache_1.restoreCache)();
let binPath = await (0, install_1.install)();
// Build custom golangci-lint if needed.
const customBinPath = await plugins.install(binPath);
if (customBinPath !== "") {
binPath = customBinPath;
}
if (installOnly) {
return { binPath, patchPath: `` };
}
const patchPath = await (0, patch_1.fetchPatch)();
core.info(`Prepared env in ${Date.now() - startedAt}ms`);
return { binPath, patchPath };
}
const execCommand = (0, util_1.promisify)(child_process_1.exec);
const printOutput = (res) => {
if (res.stdout) {
core.info(res.stdout);
@ -97481,12 +97473,7 @@ const printOutput = (res) => {
core.info(res.stderr);
}
};
async function runLint(binPath, patchPath) {
const debug = core.getInput(`debug`);
if (debug.split(`,`).includes(`cache`)) {
const res = await execShellCommand(`${binPath} cache status`);
printOutput(res);
}
async function runGolangciLint(binPath, rootDir) {
const userArgs = core.getInput(`args`);
const addedArgs = [];
const userArgsList = userArgs
@ -97498,15 +97485,6 @@ async function runLint(binPath, patchPath) {
.map(([key, value]) => [key.toLowerCase(), value ?? ""]);
const userArgsMap = new Map(userArgsList);
const userArgNames = new Set(userArgsList.map(([key]) => key));
const problemMatchers = core.getBooleanInput(`problem-matchers`);
if (problemMatchers) {
const matchersPath = path.join(__dirname, "../..", "problem-matchers.json");
if (fs.existsSync(matchersPath)) {
// Adds problem matchers.
// https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83
core.info(`##[add-matcher]${matchersPath}`);
}
}
if ((0, patch_1.isOnlyNewIssues)()) {
if (userArgNames.has(`new`) ||
userArgNames.has(`new-from-rev`) ||
@ -97515,6 +97493,7 @@ async function runLint(binPath, patchPath) {
throw new Error(`please, don't specify manually --new* args when requesting only new issues`);
}
const ctx = github.context;
const patchPath = await (0, patch_1.fetchPatch)();
core.info(`only new issues on ${ctx.eventName}: ${patchPath}`);
switch (ctx.eventName) {
case `pull_request`:
@ -97540,27 +97519,21 @@ async function runLint(binPath, patchPath) {
}
}
const cmdArgs = {};
const workingDirectory = core.getInput(`working-directory`);
if (workingDirectory) {
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
throw new Error(`working-directory (${workingDirectory}) was not a path`);
}
if (rootDir) {
if (!userArgNames.has(`path-prefix`) && !userArgNames.has(`path-mode`)) {
addedArgs.push(`--path-mode=abs`);
}
cmdArgs.cwd = path.resolve(workingDirectory);
cmdArgs.cwd = path.resolve(rootDir);
}
await runVerify(binPath, userArgsMap, cmdArgs);
const cmd = `${binPath} run ${addedArgs.join(` `)} ${userArgs}`.trimEnd();
core.info(`Running [${cmd}] in [${cmdArgs.cwd || process.cwd()}] ...`);
const startedAt = Date.now();
try {
const res = await execShellCommand(cmd, cmdArgs);
printOutput(res);
core.info(`golangci-lint found no issues`);
}
catch (exc) {
// This logging passes issues to GitHub annotations but comments can be more convenient for some users.
return execCommand(cmd, cmdArgs)
.then(printOutput)
.then(() => core.info(`golangci-lint found no issues`))
.catch((exc) => {
// This logging passes issues to GitHub annotations.
printOutput(exc);
if (exc.code === 1) {
core.setFailed(`issues found`);
@ -97568,8 +97541,8 @@ async function runLint(binPath, patchPath) {
else {
core.setFailed(`golangci-lint exit with code ${exc.code}`);
}
}
core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`);
})
.finally(() => core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`));
}
async function runVerify(binPath, userArgsMap, cmdArgs) {
const verify = core.getBooleanInput(`verify`, { required: true });
@ -97585,8 +97558,7 @@ async function runVerify(binPath, userArgsMap, cmdArgs) {
cmdVerify += ` --config=${userArgsMap.get("config")}`;
}
core.info(`Running [${cmdVerify}] in [${cmdArgs.cwd || process.cwd()}] ...`);
const res = await execShellCommand(cmdVerify, cmdArgs);
printOutput(res);
await execCommand(cmdVerify, cmdArgs).then(printOutput);
}
async function getConfigPath(binPath, userArgsMap, cmdArgs) {
let cmdConfigPath = `${binPath} config path`;
@ -97595,22 +97567,73 @@ async function getConfigPath(binPath, userArgsMap, cmdArgs) {
}
core.info(`Running [${cmdConfigPath}] in [${cmdArgs.cwd || process.cwd()}] ...`);
try {
const resPath = await execShellCommand(cmdConfigPath, cmdArgs);
const resPath = await execCommand(cmdConfigPath, cmdArgs);
return resPath.stderr.trim();
}
catch {
return ``;
}
}
async function debugAction(binPath) {
const flags = core.getInput(`debug`).split(`,`);
if (flags.includes(`clean`)) {
const cmd = `${binPath} cache clean`;
core.info(`Running [${cmd}] ...`);
await execCommand(cmd).then(printOutput);
}
if (flags.includes(`cache`)) {
const cmd = `${binPath} cache status`;
core.info(`Running [${cmd}] ...`);
await execCommand(cmd).then(printOutput);
}
}
function getWorkingDirectory() {
const workingDirectory = core.getInput(`working-directory`);
if (workingDirectory) {
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
throw new Error(`working-directory (${workingDirectory}) was not a path`);
}
}
return workingDirectory;
}
function modulesAutoDetection(rootDir) {
const o = {
cwd: rootDir,
exclude: ["**/vendor/**", "**/node_modules/**", "**/.git/**", "**/dist/**"],
};
const matches = fs.globSync("**/go.mod", o);
const dirs = matches
.filter((m) => typeof m === "string")
.map((m) => path.resolve(rootDir, path.dirname(m)))
.sort();
return [...new Set(dirs)];
}
async function runLint(binPath) {
const workingDirectory = getWorkingDirectory();
const experimental = core.getInput(`experimental`).split(`,`);
if (experimental.includes(`automatic-module-directories`)) {
const wds = modulesAutoDetection(workingDirectory);
const cwd = process.cwd();
for (const wd of wds) {
await core.group(`run golangci-lint in ${path.relative(cwd, wd)}`, () => runGolangciLint(binPath, wd));
}
return;
}
await core.group(`run golangci-lint`, () => runGolangciLint(binPath, workingDirectory));
}
async function run() {
try {
const installOnly = core.getBooleanInput(`install-only`, { required: true });
const { binPath, patchPath } = await core.group(`prepare environment`, () => prepareEnv(installOnly));
await core.group(`Restore cache`, cache_1.restoreCache);
const binPath = await core.group(`Install`, () => (0, install_1.install)().then(plugins.install));
core.addPath(path.dirname(binPath));
if (core.getInput(`debug`)) {
await core.group(`Debug`, () => debugAction(binPath));
}
const installOnly = core.getBooleanInput(`install-only`, { required: true });
if (installOnly) {
return;
}
await core.group(`run golangci-lint`, () => runLint(binPath, patchPath));
await runLint(binPath);
}
catch (error) {
core.error(`Failed to run: ${error}, ${error.stack}`);
@ -97889,6 +97912,10 @@ const isLessVersion = (a, b) => {
};
const getRequestedVersion = () => {
let requestedVersion = core.getInput(`version`);
let versionFilePath = core.getInput(`version-file`);
if (requestedVersion && versionFilePath) {
core.warning(`Both version (${requestedVersion}) and version-file (${versionFilePath}) inputs are specified, only version will be used`);
}
const workingDirectory = core.getInput(`working-directory`);
let goMod = "go.mod";
if (workingDirectory) {
@ -97902,6 +97929,24 @@ const getRequestedVersion = () => {
core.info(`Found golangci-lint version '${requestedVersion}' in '${goMod}' file`);
}
}
if (requestedVersion == "" && versionFilePath) {
if (workingDirectory) {
versionFilePath = path_1.default.join(workingDirectory, versionFilePath);
}
if (!fs.existsSync(versionFilePath)) {
throw new Error(`The specified golangci-lint version file at: ${versionFilePath} does not exist`);
}
const content = fs.readFileSync(versionFilePath, "utf-8");
if (path_1.default.basename(versionFilePath) === ".tool-versions") {
// asdf/mise file.
const match = content.match(/^golangci-lint\s+([^\n#]+)/m);
requestedVersion = match ? "v" + match[1].trim().replace(/^v/gi, "") : "";
}
else {
// .golangci-lint-version file.
requestedVersion = "v" + content.trim().replace(/^v/gi, "");
}
}
const parsedRequestedVersion = parseVersion(requestedVersion);
if (parsedRequestedVersion == null) {
return null;
@ -102683,7 +102728,7 @@ function composeCollection(CN, ctx, token, props, onError) {
let tag = ctx.schema.tags.find(t => t.tag === tagName && t.collection === expType);
if (!tag) {
const kt = ctx.schema.knownTags[tagName];
if (kt && kt.collection === expType) {
if (kt?.collection === expType) {
ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
tag = kt;
}
@ -103569,7 +103614,7 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
});
if (!props.found) {
if (props.anchor || props.tag || value) {
if (value && value.type === 'block-seq')
if (value?.type === 'block-seq')
onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
else
onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
@ -103786,7 +103831,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
}
}
else if (value) {
if ('source' in value && value.source && value.source[0] === ':')
if ('source' in value && value.source?.[0] === ':')
onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
else
onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
@ -103830,7 +103875,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
const expectedEnd = isMap ? '}' : ']';
const [ce, ...ee] = fc.end;
let cePos = offset;
if (ce && ce.source === expectedEnd)
if (ce?.source === expectedEnd)
cePos = ce.offset + ce.source.length;
else {
const name = fcName[0].toUpperCase() + fcName.substring(1);
@ -105211,7 +105256,7 @@ const prettifyError = (src, lc) => (error) => {
if (/[^ ]/.test(lineStr)) {
let count = 1;
const end = error.linePos[1];
if (end && end.line === line && end.col > col) {
if (end?.line === line && end.col > col) {
count = Math.max(1, Math.min(end.col - col, 80 - ci));
}
const pointer = ' '.repeat(ci) + '^'.repeat(count);
@ -105379,7 +105424,7 @@ class Alias extends Node.NodeBase {
data = anchors.get(source);
}
/* istanbul ignore if */
if (!data || data.res === undefined) {
if (data?.res === undefined) {
const msg = 'This should not happen: Alias anchor was not resolved?';
throw new ReferenceError(msg);
}
@ -107721,7 +107766,7 @@ class Parser {
}
*step() {
const top = this.peek(1);
if (this.type === 'doc-end' && (!top || top.type !== 'doc-end')) {
if (this.type === 'doc-end' && top?.type !== 'doc-end') {
while (this.stack.length > 0)
yield* this.pop();
this.stack.push({
@ -108253,7 +108298,7 @@ class Parser {
do {
yield* this.pop();
top = this.peek(1);
} while (top && top.type === 'flow-collection');
} while (top?.type === 'flow-collection');
}
else if (fc.end.length === 0) {
switch (this.type) {
@ -110439,7 +110484,7 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
const num = typeof value === 'number' ? value : Number(value);
if (!isFinite(num))
return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
let n = JSON.stringify(value);
let n = Object.is(value, -0) ? '-0' : JSON.stringify(value);
if (!format &&
minFractionDigits &&
(!tag || tag === 'tag:yaml.org,2002:float') &&
@ -110570,7 +110615,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
ws += `\n${stringifyComment.indentComment(cs, ctx.indent)}`;
}
if (valueStr === '' && !ctx.inFlow) {
if (ws === '\n')
if (ws === '\n' && valueComment)
ws = '\n\n';
}
else {

229
dist/run/index.js generated vendored
View file

@ -96844,8 +96844,10 @@ async function buildCacheKeys() {
return keys;
}
async function restoreCache() {
if (core.getBooleanInput(`skip-cache`, { required: true }))
if (core.getBooleanInput(`skip-cache`, { required: true })) {
core.info(`Skipping cache restoration`);
return;
}
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
return;
@ -96881,10 +96883,14 @@ async function restoreCache() {
}
}
async function saveCache() {
if (core.getBooleanInput(`skip-cache`, { required: true }))
if (core.getBooleanInput(`skip-cache`, { required: true })) {
core.info(`Skipping cache saving`);
return;
if (core.getBooleanInput(`skip-save-cache`, { required: true }))
}
if (core.getBooleanInput(`skip-save-cache`, { required: true })) {
core.info(`Skipping cache saving`);
return;
}
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {
utils.logWarning(`Event Validation Error: The event type ${process.env[constants_1.Events.Key]} is not supported because it's not tied to a branch or tag ref.`);
@ -96999,12 +97005,13 @@ exports.installBinary = installBinary;
const core = __importStar(__nccwpck_require__(37484));
const tc = __importStar(__nccwpck_require__(33472));
const child_process_1 = __nccwpck_require__(35317);
const fs_1 = __importDefault(__nccwpck_require__(79896));
const os_1 = __importDefault(__nccwpck_require__(70857));
const path_1 = __importDefault(__nccwpck_require__(16928));
const util_1 = __nccwpck_require__(39023);
const which_1 = __importDefault(__nccwpck_require__(11189));
const version_1 = __nccwpck_require__(311);
const execShellCommand = (0, util_1.promisify)(child_process_1.exec);
const execCommand = (0, util_1.promisify)(child_process_1.exec);
var InstallMode;
(function (InstallMode) {
InstallMode["Binary"] = "binary";
@ -97018,6 +97025,7 @@ const printOutput = (res) => {
if (res.stderr) {
core.info(res.stderr);
}
return res;
};
/**
* Install golangci-lint.
@ -97025,6 +97033,15 @@ const printOutput = (res) => {
* @returns path to installed binary of golangci-lint.
*/
async function install() {
const problemMatchers = core.getBooleanInput(`problem-matchers`);
if (problemMatchers) {
const matchersPath = path_1.default.join(__dirname, "../..", "problem-matchers.json");
if (fs_1.default.existsSync(matchersPath)) {
// Adds problem matchers.
// https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83
core.info(`##[add-matcher]${matchersPath}`);
}
}
const mode = core.getInput("install-mode").toLowerCase();
if (mode === InstallMode.None) {
const binPath = await (0, which_1.default)("golangci-lint", { nothrow: true });
@ -97064,10 +97081,8 @@ async function goInstall(versionInfo) {
core.info(`Installing golangci-lint ${versionInfo.TargetVersion}...`);
const startedAt = Date.now();
const options = { env: { ...process.env, CGO_ENABLED: "1" } };
const exres = await execShellCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options);
printOutput(exres);
const res = await execShellCommand(`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options);
printOutput(res);
await execCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then(printOutput);
const res = await execCommand(`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then(printOutput);
// The output of `go install -n` when the binary is already installed is `touch <path_to_the_binary>`.
const binPath = res.stderr
.split(/\r?\n/)
@ -97196,9 +97211,6 @@ function isOnlyNewIssues() {
return core.getBooleanInput(`only-new-issues`, { required: true });
}
async function fetchPatch() {
if (!isOnlyNewIssues()) {
return ``;
}
const ctx = github.context;
switch (ctx.eventName) {
case `pull_request`:
@ -97242,8 +97254,7 @@ async function fetchPullRequestPatch(ctx) {
return ``; // don't fail the action, but analyze without patch
}
try {
const tempDir = await createTempDir();
const patchPath = path_1.default.join(tempDir, "pull.patch");
const patchPath = await createTempDir().then((tempDir) => path_1.default.join(tempDir, "pull.patch"));
core.info(`Writing patch to ${patchPath}`);
await writeFile(patchPath, (0, diffUtils_1.alterDiffPatch)(patch));
return patchPath;
@ -97277,8 +97288,7 @@ async function fetchPushPatch(ctx) {
return ``; // don't fail the action, but analyze without patch
}
try {
const tempDir = await createTempDir();
const patchPath = path_1.default.join(tempDir, "push.patch");
const patchPath = await createTempDir().then((tempDir) => path_1.default.join(tempDir, "push.patch"));
core.info(`Writing patch to ${patchPath}`);
await writeFile(patchPath, (0, diffUtils_1.alterDiffPatch)(patch));
return patchPath;
@ -97341,7 +97351,7 @@ const fs = __importStar(__nccwpck_require__(79896));
const path = __importStar(__nccwpck_require__(16928));
const util_1 = __nccwpck_require__(39023);
const yaml_1 = __importDefault(__nccwpck_require__(38815));
const execShellCommand = (0, util_1.promisify)(child_process_1.exec);
const execCommand = (0, util_1.promisify)(child_process_1.exec);
const printOutput = (res) => {
if (res.stdout) {
core.info(res.stdout);
@ -97361,11 +97371,12 @@ async function install(binPath) {
else {
rootDir = process.cwd();
}
const configFile = [".custom-gcl.yml", ".custom-gcl.yaml", ".custom-gcl.json"]
.map((v) => path.join(rootDir, v))
const configFile = ["yml", "yaml", "json"]
.map((ext) => `.custom-gcl.${ext}`)
.map((filename) => path.join(rootDir, filename))
.find((filePath) => fs.existsSync(filePath));
if (!configFile || configFile === "") {
return "";
return binPath;
}
core.info(`Found configuration for the plugin module system : ${configFile}`);
core.info(`Building and installing custom golangci-lint binary...`);
@ -97373,7 +97384,7 @@ async function install(binPath) {
const config = yaml_1.default.parse(fs.readFileSync(configFile, "utf-8"));
const v = core.getInput(`version`);
if (v !== "" && config.version !== v) {
core.warning(`The golangci-lint version (${config.version}) defined inside in ${configFile} does not match the version defined in the action (${v})`);
core.warning(`The golangci-lint version (${config.version}) defined inside ${configFile} does not match the version defined in the action (${v})`);
}
if (!config.destination) {
config.destination = ".";
@ -97387,18 +97398,16 @@ async function install(binPath) {
}
const cmd = `${binPath} custom`;
core.info(`Running [${cmd}] in [${rootDir}] ...`);
try {
const options = {
cwd: rootDir,
};
const res = await execShellCommand(cmd, options);
printOutput(res);
core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`);
return path.join(rootDir, config.destination, config.name);
}
catch (exc) {
return execCommand(cmd, options)
.then(printOutput)
.then(() => core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`))
.then(() => path.join(rootDir, config.destination, config.name))
.catch((exc) => {
throw new Error(`Failed to build custom golangci-lint binary: ${exc.message}`);
}
});
}
@ -97455,24 +97464,7 @@ const cache_1 = __nccwpck_require__(97377);
const install_1 = __nccwpck_require__(90232);
const patch_1 = __nccwpck_require__(47161);
const plugins = __importStar(__nccwpck_require__(96067));
const execShellCommand = (0, util_1.promisify)(child_process_1.exec);
async function prepareEnv(installOnly) {
const startedAt = Date.now();
// Prepare cache, lint and go in parallel.
await (0, cache_1.restoreCache)();
let binPath = await (0, install_1.install)();
// Build custom golangci-lint if needed.
const customBinPath = await plugins.install(binPath);
if (customBinPath !== "") {
binPath = customBinPath;
}
if (installOnly) {
return { binPath, patchPath: `` };
}
const patchPath = await (0, patch_1.fetchPatch)();
core.info(`Prepared env in ${Date.now() - startedAt}ms`);
return { binPath, patchPath };
}
const execCommand = (0, util_1.promisify)(child_process_1.exec);
const printOutput = (res) => {
if (res.stdout) {
core.info(res.stdout);
@ -97481,12 +97473,7 @@ const printOutput = (res) => {
core.info(res.stderr);
}
};
async function runLint(binPath, patchPath) {
const debug = core.getInput(`debug`);
if (debug.split(`,`).includes(`cache`)) {
const res = await execShellCommand(`${binPath} cache status`);
printOutput(res);
}
async function runGolangciLint(binPath, rootDir) {
const userArgs = core.getInput(`args`);
const addedArgs = [];
const userArgsList = userArgs
@ -97498,15 +97485,6 @@ async function runLint(binPath, patchPath) {
.map(([key, value]) => [key.toLowerCase(), value ?? ""]);
const userArgsMap = new Map(userArgsList);
const userArgNames = new Set(userArgsList.map(([key]) => key));
const problemMatchers = core.getBooleanInput(`problem-matchers`);
if (problemMatchers) {
const matchersPath = path.join(__dirname, "../..", "problem-matchers.json");
if (fs.existsSync(matchersPath)) {
// Adds problem matchers.
// https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83
core.info(`##[add-matcher]${matchersPath}`);
}
}
if ((0, patch_1.isOnlyNewIssues)()) {
if (userArgNames.has(`new`) ||
userArgNames.has(`new-from-rev`) ||
@ -97515,6 +97493,7 @@ async function runLint(binPath, patchPath) {
throw new Error(`please, don't specify manually --new* args when requesting only new issues`);
}
const ctx = github.context;
const patchPath = await (0, patch_1.fetchPatch)();
core.info(`only new issues on ${ctx.eventName}: ${patchPath}`);
switch (ctx.eventName) {
case `pull_request`:
@ -97540,27 +97519,21 @@ async function runLint(binPath, patchPath) {
}
}
const cmdArgs = {};
const workingDirectory = core.getInput(`working-directory`);
if (workingDirectory) {
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
throw new Error(`working-directory (${workingDirectory}) was not a path`);
}
if (rootDir) {
if (!userArgNames.has(`path-prefix`) && !userArgNames.has(`path-mode`)) {
addedArgs.push(`--path-mode=abs`);
}
cmdArgs.cwd = path.resolve(workingDirectory);
cmdArgs.cwd = path.resolve(rootDir);
}
await runVerify(binPath, userArgsMap, cmdArgs);
const cmd = `${binPath} run ${addedArgs.join(` `)} ${userArgs}`.trimEnd();
core.info(`Running [${cmd}] in [${cmdArgs.cwd || process.cwd()}] ...`);
const startedAt = Date.now();
try {
const res = await execShellCommand(cmd, cmdArgs);
printOutput(res);
core.info(`golangci-lint found no issues`);
}
catch (exc) {
// This logging passes issues to GitHub annotations but comments can be more convenient for some users.
return execCommand(cmd, cmdArgs)
.then(printOutput)
.then(() => core.info(`golangci-lint found no issues`))
.catch((exc) => {
// This logging passes issues to GitHub annotations.
printOutput(exc);
if (exc.code === 1) {
core.setFailed(`issues found`);
@ -97568,8 +97541,8 @@ async function runLint(binPath, patchPath) {
else {
core.setFailed(`golangci-lint exit with code ${exc.code}`);
}
}
core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`);
})
.finally(() => core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`));
}
async function runVerify(binPath, userArgsMap, cmdArgs) {
const verify = core.getBooleanInput(`verify`, { required: true });
@ -97585,8 +97558,7 @@ async function runVerify(binPath, userArgsMap, cmdArgs) {
cmdVerify += ` --config=${userArgsMap.get("config")}`;
}
core.info(`Running [${cmdVerify}] in [${cmdArgs.cwd || process.cwd()}] ...`);
const res = await execShellCommand(cmdVerify, cmdArgs);
printOutput(res);
await execCommand(cmdVerify, cmdArgs).then(printOutput);
}
async function getConfigPath(binPath, userArgsMap, cmdArgs) {
let cmdConfigPath = `${binPath} config path`;
@ -97595,22 +97567,73 @@ async function getConfigPath(binPath, userArgsMap, cmdArgs) {
}
core.info(`Running [${cmdConfigPath}] in [${cmdArgs.cwd || process.cwd()}] ...`);
try {
const resPath = await execShellCommand(cmdConfigPath, cmdArgs);
const resPath = await execCommand(cmdConfigPath, cmdArgs);
return resPath.stderr.trim();
}
catch {
return ``;
}
}
async function debugAction(binPath) {
const flags = core.getInput(`debug`).split(`,`);
if (flags.includes(`clean`)) {
const cmd = `${binPath} cache clean`;
core.info(`Running [${cmd}] ...`);
await execCommand(cmd).then(printOutput);
}
if (flags.includes(`cache`)) {
const cmd = `${binPath} cache status`;
core.info(`Running [${cmd}] ...`);
await execCommand(cmd).then(printOutput);
}
}
function getWorkingDirectory() {
const workingDirectory = core.getInput(`working-directory`);
if (workingDirectory) {
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
throw new Error(`working-directory (${workingDirectory}) was not a path`);
}
}
return workingDirectory;
}
function modulesAutoDetection(rootDir) {
const o = {
cwd: rootDir,
exclude: ["**/vendor/**", "**/node_modules/**", "**/.git/**", "**/dist/**"],
};
const matches = fs.globSync("**/go.mod", o);
const dirs = matches
.filter((m) => typeof m === "string")
.map((m) => path.resolve(rootDir, path.dirname(m)))
.sort();
return [...new Set(dirs)];
}
async function runLint(binPath) {
const workingDirectory = getWorkingDirectory();
const experimental = core.getInput(`experimental`).split(`,`);
if (experimental.includes(`automatic-module-directories`)) {
const wds = modulesAutoDetection(workingDirectory);
const cwd = process.cwd();
for (const wd of wds) {
await core.group(`run golangci-lint in ${path.relative(cwd, wd)}`, () => runGolangciLint(binPath, wd));
}
return;
}
await core.group(`run golangci-lint`, () => runGolangciLint(binPath, workingDirectory));
}
async function run() {
try {
const installOnly = core.getBooleanInput(`install-only`, { required: true });
const { binPath, patchPath } = await core.group(`prepare environment`, () => prepareEnv(installOnly));
await core.group(`Restore cache`, cache_1.restoreCache);
const binPath = await core.group(`Install`, () => (0, install_1.install)().then(plugins.install));
core.addPath(path.dirname(binPath));
if (core.getInput(`debug`)) {
await core.group(`Debug`, () => debugAction(binPath));
}
const installOnly = core.getBooleanInput(`install-only`, { required: true });
if (installOnly) {
return;
}
await core.group(`run golangci-lint`, () => runLint(binPath, patchPath));
await runLint(binPath);
}
catch (error) {
core.error(`Failed to run: ${error}, ${error.stack}`);
@ -97889,6 +97912,10 @@ const isLessVersion = (a, b) => {
};
const getRequestedVersion = () => {
let requestedVersion = core.getInput(`version`);
let versionFilePath = core.getInput(`version-file`);
if (requestedVersion && versionFilePath) {
core.warning(`Both version (${requestedVersion}) and version-file (${versionFilePath}) inputs are specified, only version will be used`);
}
const workingDirectory = core.getInput(`working-directory`);
let goMod = "go.mod";
if (workingDirectory) {
@ -97902,6 +97929,24 @@ const getRequestedVersion = () => {
core.info(`Found golangci-lint version '${requestedVersion}' in '${goMod}' file`);
}
}
if (requestedVersion == "" && versionFilePath) {
if (workingDirectory) {
versionFilePath = path_1.default.join(workingDirectory, versionFilePath);
}
if (!fs.existsSync(versionFilePath)) {
throw new Error(`The specified golangci-lint version file at: ${versionFilePath} does not exist`);
}
const content = fs.readFileSync(versionFilePath, "utf-8");
if (path_1.default.basename(versionFilePath) === ".tool-versions") {
// asdf/mise file.
const match = content.match(/^golangci-lint\s+([^\n#]+)/m);
requestedVersion = match ? "v" + match[1].trim().replace(/^v/gi, "") : "";
}
else {
// .golangci-lint-version file.
requestedVersion = "v" + content.trim().replace(/^v/gi, "");
}
}
const parsedRequestedVersion = parseVersion(requestedVersion);
if (parsedRequestedVersion == null) {
return null;
@ -102683,7 +102728,7 @@ function composeCollection(CN, ctx, token, props, onError) {
let tag = ctx.schema.tags.find(t => t.tag === tagName && t.collection === expType);
if (!tag) {
const kt = ctx.schema.knownTags[tagName];
if (kt && kt.collection === expType) {
if (kt?.collection === expType) {
ctx.schema.tags.push(Object.assign({}, kt, { default: false }));
tag = kt;
}
@ -103569,7 +103614,7 @@ function resolveBlockSeq({ composeNode, composeEmptyNode }, ctx, bs, onError, ta
});
if (!props.found) {
if (props.anchor || props.tag || value) {
if (value && value.type === 'block-seq')
if (value?.type === 'block-seq')
onError(props.end, 'BAD_INDENT', 'All sequence items must start at the same column');
else
onError(offset, 'MISSING_CHAR', 'Sequence item without - indicator');
@ -103786,7 +103831,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
}
}
else if (value) {
if ('source' in value && value.source && value.source[0] === ':')
if ('source' in value && value.source?.[0] === ':')
onError(value, 'MISSING_CHAR', `Missing space after : in ${fcName}`);
else
onError(valueProps.start, 'MISSING_CHAR', `Missing , or : between ${fcName} items`);
@ -103830,7 +103875,7 @@ function resolveFlowCollection({ composeNode, composeEmptyNode }, ctx, fc, onErr
const expectedEnd = isMap ? '}' : ']';
const [ce, ...ee] = fc.end;
let cePos = offset;
if (ce && ce.source === expectedEnd)
if (ce?.source === expectedEnd)
cePos = ce.offset + ce.source.length;
else {
const name = fcName[0].toUpperCase() + fcName.substring(1);
@ -105211,7 +105256,7 @@ const prettifyError = (src, lc) => (error) => {
if (/[^ ]/.test(lineStr)) {
let count = 1;
const end = error.linePos[1];
if (end && end.line === line && end.col > col) {
if (end?.line === line && end.col > col) {
count = Math.max(1, Math.min(end.col - col, 80 - ci));
}
const pointer = ' '.repeat(ci) + '^'.repeat(count);
@ -105379,7 +105424,7 @@ class Alias extends Node.NodeBase {
data = anchors.get(source);
}
/* istanbul ignore if */
if (!data || data.res === undefined) {
if (data?.res === undefined) {
const msg = 'This should not happen: Alias anchor was not resolved?';
throw new ReferenceError(msg);
}
@ -107721,7 +107766,7 @@ class Parser {
}
*step() {
const top = this.peek(1);
if (this.type === 'doc-end' && (!top || top.type !== 'doc-end')) {
if (this.type === 'doc-end' && top?.type !== 'doc-end') {
while (this.stack.length > 0)
yield* this.pop();
this.stack.push({
@ -108253,7 +108298,7 @@ class Parser {
do {
yield* this.pop();
top = this.peek(1);
} while (top && top.type === 'flow-collection');
} while (top?.type === 'flow-collection');
}
else if (fc.end.length === 0) {
switch (this.type) {
@ -110439,7 +110484,7 @@ function stringifyNumber({ format, minFractionDigits, tag, value }) {
const num = typeof value === 'number' ? value : Number(value);
if (!isFinite(num))
return isNaN(num) ? '.nan' : num < 0 ? '-.inf' : '.inf';
let n = JSON.stringify(value);
let n = Object.is(value, -0) ? '-0' : JSON.stringify(value);
if (!format &&
minFractionDigits &&
(!tag || tag === 'tag:yaml.org,2002:float') &&
@ -110570,7 +110615,7 @@ function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
ws += `\n${stringifyComment.indentComment(cs, ctx.indent)}`;
}
if (valueStr === '' && !ctx.inFlow) {
if (ws === '\n')
if (ws === '\n' && valueComment)
ws = '\n\n';
}
else {

View file

@ -1,4 +1,4 @@
module sample
module github.com/golangci/sample
go 1.24.0

View file

@ -1,4 +1,4 @@
module sample
module github.com/golangci/sample
go 1.24.0

View file

@ -0,0 +1,3 @@
module github.com/golangci/actiona
go 1.24.0

View file

@ -0,0 +1,3 @@
module github.com/golangci/actiona/suba
go 1.24.0

View file

@ -0,0 +1,26 @@
// Package sample is used as test input for golangci action.
package sample
import (
"crypto/md5"
"encoding/hex"
"errors"
)
// Hash~
func Hash(data string) string {
retError()
retError2()
h := md5.New()
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
func retError() error {
return errors.New("err")
}
func retError2() error {
return errors.New("err2")
}

View file

@ -0,0 +1,3 @@
module github.com/golangci/actionb
go 1.24.0

View file

@ -0,0 +1,26 @@
// Package sample is used as test input for golangci action.
package sample
import (
"crypto/md5"
"encoding/hex"
"errors"
)
// Hash~
func Hash(data string) string {
retError()
retError2()
h := md5.New()
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
func retError() error {
return errors.New("err")
}
func retError2() error {
return errors.New("err2")
}

View file

@ -0,0 +1,3 @@
module github.com/golangci/actionc
go 1.24.0

View file

@ -0,0 +1,26 @@
// Package sample is used as test input for golangci action.
package sample
import (
"crypto/md5"
"encoding/hex"
"errors"
)
// Hash~
func Hash(data string) string {
retError()
retError2()
h := md5.New()
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
func retError() error {
return errors.New("err")
}
func retError2() error {
return errors.New("err2")
}

26
fixtures/simple/sample.go Normal file
View file

@ -0,0 +1,26 @@
// Package sample is used as test input for golangci action.
package sample
import (
"crypto/md5"
"encoding/hex"
"errors"
)
// Hash~
func Hash(data string) string {
retError()
retError2()
h := md5.New()
h.Write([]byte(data))
return hex.EncodeToString(h.Sum(nil))
}
func retError() error {
return errors.New("err")
}
func retError2() error {
return errors.New("err2")
}

2
go.mod
View file

@ -1,3 +1,3 @@
module github.com/golangci/golangci-lint-action
go 1.23
go 1.24.0

313
package-lock.json generated
View file

@ -16,16 +16,16 @@
"@actions/http-client": "^3.0.0",
"@actions/tool-cache": "^2.0.2",
"@octokit/plugin-retry": "^6.1.0",
"@types/node": "^24.10.0",
"@types/node": "^24.10.1",
"@types/semver": "^7.7.1",
"@types/tmp": "^0.2.6",
"@types/which": "^3.0.4",
"tmp": "^0.2.5",
"which": "^5.0.0",
"yaml": "^2.8.1"
"which": "^6.0.0",
"yaml": "^2.8.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.32.1",
"@vercel/ncc": "^0.38.4",
"eslint": "^8.57.1",
@ -33,7 +33,7 @@
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-simple-import-sort": "^12.1.1",
"prettier": "^3.6.2",
"prettier": "^3.7.4",
"typescript": "^5.9.3"
},
"engines": {
@ -528,6 +528,7 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz",
"integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==",
"peer": true,
"dependencies": {
"@octokit/auth-token": "^4.0.0",
"@octokit/graphql": "^7.1.0",
@ -730,9 +731,9 @@
"dev": true
},
"node_modules/@types/node": {
"version": "24.10.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz",
"integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==",
"version": "24.10.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
@ -788,17 +789,17 @@
"integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz",
"integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz",
"integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/type-utils": "8.46.2",
"@typescript-eslint/utils": "8.46.2",
"@typescript-eslint/visitor-keys": "8.46.2",
"@typescript-eslint/scope-manager": "8.48.1",
"@typescript-eslint/type-utils": "8.48.1",
"@typescript-eslint/utils": "8.48.1",
"@typescript-eslint/visitor-keys": "8.48.1",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
@ -812,7 +813,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.46.2",
"@typescript-eslint/parser": "^8.48.1",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
@ -828,16 +829,17 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz",
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz",
"integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/types": "8.46.2",
"@typescript-eslint/typescript-estree": "8.46.2",
"@typescript-eslint/visitor-keys": "8.46.2",
"@typescript-eslint/scope-manager": "8.48.1",
"@typescript-eslint/types": "8.48.1",
"@typescript-eslint/typescript-estree": "8.48.1",
"@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4"
},
"engines": {
@ -853,14 +855,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz",
"integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz",
"integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.46.2",
"@typescript-eslint/types": "^8.46.2",
"@typescript-eslint/tsconfig-utils": "^8.48.1",
"@typescript-eslint/types": "^8.48.1",
"debug": "^4.3.4"
},
"engines": {
@ -875,14 +877,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz",
"integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz",
"integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.46.2",
"@typescript-eslint/visitor-keys": "8.46.2"
"@typescript-eslint/types": "8.48.1",
"@typescript-eslint/visitor-keys": "8.48.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -893,9 +895,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz",
"integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz",
"integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==",
"dev": true,
"license": "MIT",
"engines": {
@ -910,15 +912,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz",
"integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz",
"integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.46.2",
"@typescript-eslint/typescript-estree": "8.46.2",
"@typescript-eslint/utils": "8.46.2",
"@typescript-eslint/types": "8.48.1",
"@typescript-eslint/typescript-estree": "8.48.1",
"@typescript-eslint/utils": "8.48.1",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
@ -935,9 +937,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz",
"integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
"integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
"dev": true,
"license": "MIT",
"engines": {
@ -949,21 +951,20 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz",
"integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz",
"integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.46.2",
"@typescript-eslint/tsconfig-utils": "8.46.2",
"@typescript-eslint/types": "8.46.2",
"@typescript-eslint/visitor-keys": "8.46.2",
"@typescript-eslint/project-service": "8.48.1",
"@typescript-eslint/tsconfig-utils": "8.48.1",
"@typescript-eslint/types": "8.48.1",
"@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"tinyglobby": "^0.2.15",
"ts-api-utils": "^2.1.0"
},
"engines": {
@ -1017,16 +1018,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz",
"integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz",
"integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/types": "8.46.2",
"@typescript-eslint/typescript-estree": "8.46.2"
"@typescript-eslint/scope-manager": "8.48.1",
"@typescript-eslint/types": "8.48.1",
"@typescript-eslint/typescript-estree": "8.48.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -1041,13 +1042,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.46.2",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz",
"integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==",
"version": "8.48.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz",
"integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.46.2",
"@typescript-eslint/types": "8.48.1",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@ -1103,6 +1104,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -1344,19 +1346,6 @@
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@ -1811,6 +1800,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
"dev": true,
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@ -1867,6 +1857,7 @@
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@ -2135,36 +2126,6 @@
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
"dev": true
},
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.8"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@ -2186,6 +2147,24 @@
"reusify": "^1.0.4"
}
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -2198,19 +2177,6 @@
"node": "^10.12.0 || >=12.0.0"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@ -2831,16 +2797,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-number-object": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
@ -3028,10 +2984,11 @@
}
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@ -3121,30 +3078,6 @@
"node": ">= 0.4"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@ -3428,13 +3361,14 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=8.6"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
@ -3460,10 +3394,12 @@
}
},
"node_modules/prettier": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"version": "3.7.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
"integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@ -4025,6 +3961,23 @@
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
"dev": true
},
"node_modules/tinyglobby": {
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tmp": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
@ -4034,19 +3987,6 @@
"node": ">=14.14"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@ -4199,6 +4139,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -4273,9 +4214,10 @@
}
},
"node_modules/which": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz",
"integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==",
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz",
"integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==",
"license": "ISC",
"dependencies": {
"isexe": "^3.1.1"
},
@ -4283,7 +4225,7 @@
"node-which": "bin/which.js"
},
"engines": {
"node": "^18.17.0 || >=20.5.0"
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/which-boxed-primitive": {
@ -4410,15 +4352,18 @@
}
},
"node_modules/yaml": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
},
"node_modules/yocto-queue": {

View file

@ -34,16 +34,16 @@
"@actions/http-client": "^3.0.0",
"@octokit/plugin-retry": "^6.1.0",
"@actions/tool-cache": "^2.0.2",
"@types/node": "^24.10.0",
"@types/node": "^24.10.1",
"@types/semver": "^7.7.1",
"@types/tmp": "^0.2.6",
"@types/which": "^3.0.4",
"tmp": "^0.2.5",
"which": "^5.0.0",
"yaml": "^2.8.1"
"which": "^6.0.0",
"yaml": "^2.8.2"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.46.2",
"@typescript-eslint/eslint-plugin": "^8.48.1",
"@typescript-eslint/parser": "^8.32.1",
"@vercel/ncc": "^0.38.4",
"eslint": "^8.57.1",
@ -51,7 +51,7 @@
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-simple-import-sort": "^12.1.1",
"prettier": "^3.6.2",
"prettier": "^3.7.4",
"typescript": "^5.9.3"
}
}

View file

@ -74,7 +74,10 @@ async function buildCacheKeys(): Promise<string[]> {
}
export async function restoreCache(): Promise<void> {
if (core.getBooleanInput(`skip-cache`, { required: true })) return
if (core.getBooleanInput(`skip-cache`, { required: true })) {
core.info(`Skipping cache restoration`)
return
}
if (!utils.isValidEvent()) {
utils.logWarning(
@ -116,8 +119,15 @@ export async function restoreCache(): Promise<void> {
}
export async function saveCache(): Promise<void> {
if (core.getBooleanInput(`skip-cache`, { required: true })) return
if (core.getBooleanInput(`skip-save-cache`, { required: true })) return
if (core.getBooleanInput(`skip-cache`, { required: true })) {
core.info(`Skipping cache saving`)
return
}
if (core.getBooleanInput(`skip-save-cache`, { required: true })) {
core.info(`Skipping cache saving`)
return
}
// Validate inputs, this can cause task failure
if (!utils.isValidEvent()) {

View file

@ -1,6 +1,7 @@
import * as core from "@actions/core"
import * as tc from "@actions/tool-cache"
import { exec, ExecOptionsWithStringEncoding } from "child_process"
import fs from "fs"
import os from "os"
import path from "path"
import { promisify } from "util"
@ -8,7 +9,7 @@ import which from "which"
import { getVersion, VersionInfo } from "./version"
const execShellCommand = promisify(exec)
const execCommand = promisify(exec)
export enum InstallMode {
Binary = "binary",
@ -21,13 +22,15 @@ type ExecRes = {
stderr: string
}
const printOutput = (res: ExecRes): void => {
const printOutput = (res: ExecRes): ExecRes => {
if (res.stdout) {
core.info(res.stdout)
}
if (res.stderr) {
core.info(res.stderr)
}
return res
}
/**
@ -36,6 +39,17 @@ const printOutput = (res: ExecRes): void => {
* @returns path to installed binary of golangci-lint.
*/
export async function install(): Promise<string> {
const problemMatchers = core.getBooleanInput(`problem-matchers`)
if (problemMatchers) {
const matchersPath = path.join(__dirname, "../..", "problem-matchers.json")
if (fs.existsSync(matchersPath)) {
// Adds problem matchers.
// https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83
core.info(`##[add-matcher]${matchersPath}`)
}
}
const mode = core.getInput("install-mode").toLowerCase()
if (mode === InstallMode.None) {
@ -84,17 +98,14 @@ async function goInstall(versionInfo: VersionInfo): Promise<string> {
const options: ExecOptionsWithStringEncoding = { env: { ...process.env, CGO_ENABLED: "1" } }
const exres = await execShellCommand(
`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`,
options
await execCommand(`go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`, options).then(
printOutput
)
printOutput(exres)
const res = await execShellCommand(
const res = await execCommand(
`go install -n github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${versionInfo.TargetVersion}`,
options
)
printOutput(res)
).then(printOutput)
// The output of `go install -n` when the binary is already installed is `touch <path_to_the_binary>`.
const binPath = res.stderr

View file

@ -17,10 +17,6 @@ export function isOnlyNewIssues(): boolean {
}
export async function fetchPatch(): Promise<string> {
if (!isOnlyNewIssues()) {
return ``
}
const ctx = github.context
switch (ctx.eventName) {
@ -70,8 +66,7 @@ async function fetchPullRequestPatch(ctx: Context): Promise<string> {
}
try {
const tempDir = await createTempDir()
const patchPath = path.join(tempDir, "pull.patch")
const patchPath = await createTempDir().then((tempDir) => path.join(tempDir, "pull.patch"))
core.info(`Writing patch to ${patchPath}`)
await writeFile(patchPath, alterDiffPatch(patch))
return patchPath
@ -108,8 +103,7 @@ async function fetchPushPatch(ctx: Context): Promise<string> {
}
try {
const tempDir = await createTempDir()
const patchPath = path.join(tempDir, "push.patch")
const patchPath = await createTempDir().then((tempDir) => path.join(tempDir, "push.patch"))
core.info(`Writing patch to ${patchPath}`)
await writeFile(patchPath, alterDiffPatch(patch))
return patchPath

View file

@ -5,7 +5,7 @@ import * as path from "path"
import { promisify } from "util"
import YAML from "yaml"
const execShellCommand = promisify(exec)
const execCommand = promisify(exec)
type ExecRes = {
stdout: string
@ -34,12 +34,13 @@ export async function install(binPath: string): Promise<string> {
rootDir = process.cwd()
}
const configFile = [".custom-gcl.yml", ".custom-gcl.yaml", ".custom-gcl.json"]
.map((v) => path.join(rootDir, v))
const configFile = ["yml", "yaml", "json"]
.map((ext) => `.custom-gcl.${ext}`)
.map((filename) => path.join(rootDir, filename))
.find((filePath) => fs.existsSync(filePath))
if (!configFile || configFile === "") {
return ""
return binPath
}
core.info(`Found configuration for the plugin module system : ${configFile}`)
@ -53,7 +54,7 @@ export async function install(binPath: string): Promise<string> {
const v: string = core.getInput(`version`)
if (v !== "" && config.version !== v) {
core.warning(
`The golangci-lint version (${config.version}) defined inside in ${configFile} does not match the version defined in the action (${v})`
`The golangci-lint version (${config.version}) defined inside ${configFile} does not match the version defined in the action (${v})`
)
}
@ -73,18 +74,15 @@ export async function install(binPath: string): Promise<string> {
core.info(`Running [${cmd}] in [${rootDir}] ...`)
try {
const options: ExecOptionsWithStringEncoding = {
cwd: rootDir,
}
const res = await execShellCommand(cmd, options)
printOutput(res)
core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`)
return path.join(rootDir, config.destination, config.name)
} catch (exc) {
return execCommand(cmd, options)
.then(printOutput)
.then(() => core.info(`Built custom golangci-lint binary in ${Date.now() - startedAt}ms`))
.then(() => path.join(rootDir, config.destination, config.name))
.catch((exc) => {
throw new Error(`Failed to build custom golangci-lint binary: ${exc.message}`)
}
})
}

View file

@ -10,37 +10,7 @@ import { install } from "./install"
import { fetchPatch, isOnlyNewIssues } from "./patch"
import * as plugins from "./plugins"
const execShellCommand = promisify(exec)
type Env = {
binPath: string
patchPath: string
}
async function prepareEnv(installOnly: boolean): Promise<Env> {
const startedAt = Date.now()
// Prepare cache, lint and go in parallel.
await restoreCache()
let binPath = await install()
// Build custom golangci-lint if needed.
const customBinPath = await plugins.install(binPath)
if (customBinPath !== "") {
binPath = customBinPath
}
if (installOnly) {
return { binPath, patchPath: `` }
}
const patchPath = await fetchPatch()
core.info(`Prepared env in ${Date.now() - startedAt}ms`)
return { binPath, patchPath }
}
const execCommand = promisify(exec)
type ExecRes = {
stdout: string
@ -56,13 +26,7 @@ const printOutput = (res: ExecRes): void => {
}
}
async function runLint(binPath: string, patchPath: string): Promise<void> {
const debug = core.getInput(`debug`)
if (debug.split(`,`).includes(`cache`)) {
const res = await execShellCommand(`${binPath} cache status`)
printOutput(res)
}
async function runGolangciLint(binPath: string, rootDir: string): Promise<void> {
const userArgs = core.getInput(`args`)
const addedArgs: string[] = []
@ -77,17 +41,6 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
const userArgsMap = new Map<string, string>(userArgsList)
const userArgNames = new Set<string>(userArgsList.map(([key]) => key))
const problemMatchers = core.getBooleanInput(`problem-matchers`)
if (problemMatchers) {
const matchersPath = path.join(__dirname, "../..", "problem-matchers.json")
if (fs.existsSync(matchersPath)) {
// Adds problem matchers.
// https://github.com/actions/setup-go/blob/cdcb36043654635271a94b9a6d1392de5bb323a7/src/main.ts#L81-L83
core.info(`##[add-matcher]${matchersPath}`)
}
}
if (isOnlyNewIssues()) {
if (
userArgNames.has(`new`) ||
@ -99,6 +52,7 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
}
const ctx = github.context
const patchPath = await fetchPatch()
core.info(`only new issues on ${ctx.eventName}: ${patchPath}`)
@ -130,17 +84,12 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
const cmdArgs: ExecOptionsWithStringEncoding = {}
const workingDirectory = core.getInput(`working-directory`)
if (workingDirectory) {
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
throw new Error(`working-directory (${workingDirectory}) was not a path`)
}
if (rootDir) {
if (!userArgNames.has(`path-prefix`) && !userArgNames.has(`path-mode`)) {
addedArgs.push(`--path-mode=abs`)
}
cmdArgs.cwd = path.resolve(workingDirectory)
cmdArgs.cwd = path.resolve(rootDir)
}
await runVerify(binPath, userArgsMap, cmdArgs)
@ -150,12 +99,12 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
core.info(`Running [${cmd}] in [${cmdArgs.cwd || process.cwd()}] ...`)
const startedAt = Date.now()
try {
const res = await execShellCommand(cmd, cmdArgs)
printOutput(res)
core.info(`golangci-lint found no issues`)
} catch (exc) {
// This logging passes issues to GitHub annotations but comments can be more convenient for some users.
return execCommand(cmd, cmdArgs)
.then(printOutput)
.then(() => core.info(`golangci-lint found no issues`))
.catch((exc) => {
// This logging passes issues to GitHub annotations.
printOutput(exc)
if (exc.code === 1) {
@ -163,9 +112,8 @@ async function runLint(binPath: string, patchPath: string): Promise<void> {
} else {
core.setFailed(`golangci-lint exit with code ${exc.code}`)
}
}
core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`)
})
.finally(() => core.info(`Ran golangci-lint in ${Date.now() - startedAt}ms`))
}
async function runVerify(binPath: string, userArgsMap: Map<string, string>, cmdArgs: ExecOptionsWithStringEncoding): Promise<void> {
@ -186,8 +134,7 @@ async function runVerify(binPath: string, userArgsMap: Map<string, string>, cmdA
core.info(`Running [${cmdVerify}] in [${cmdArgs.cwd || process.cwd()}] ...`)
const res = await execShellCommand(cmdVerify, cmdArgs)
printOutput(res)
await execCommand(cmdVerify, cmdArgs).then(printOutput)
}
async function getConfigPath(binPath: string, userArgsMap: Map<string, string>, cmdArgs: ExecOptionsWithStringEncoding): Promise<string> {
@ -199,26 +146,98 @@ async function getConfigPath(binPath: string, userArgsMap: Map<string, string>,
core.info(`Running [${cmdConfigPath}] in [${cmdArgs.cwd || process.cwd()}] ...`)
try {
const resPath = await execShellCommand(cmdConfigPath, cmdArgs)
const resPath = await execCommand(cmdConfigPath, cmdArgs)
return resPath.stderr.trim()
} catch {
return ``
}
}
async function debugAction(binPath: string) {
const flags = core.getInput(`debug`).split(`,`)
if (flags.includes(`clean`)) {
const cmd = `${binPath} cache clean`
core.info(`Running [${cmd}] ...`)
await execCommand(cmd).then(printOutput)
}
if (flags.includes(`cache`)) {
const cmd = `${binPath} cache status`
core.info(`Running [${cmd}] ...`)
await execCommand(cmd).then(printOutput)
}
}
function getWorkingDirectory(): string {
const workingDirectory = core.getInput(`working-directory`)
if (workingDirectory) {
if (!fs.existsSync(workingDirectory) || !fs.lstatSync(workingDirectory).isDirectory()) {
throw new Error(`working-directory (${workingDirectory}) was not a path`)
}
}
return workingDirectory
}
function modulesAutoDetection(rootDir: string): string[] {
const o: fs.GlobOptions = {
cwd: rootDir,
exclude: ["**/vendor/**", "**/node_modules/**", "**/.git/**", "**/dist/**"],
}
const matches = fs.globSync("**/go.mod", o)
const dirs = matches
.filter((m) => typeof m === "string")
.map((m) => path.resolve(rootDir, path.dirname(m)))
.sort()
return [...new Set(dirs)]
}
async function runLint(binPath: string): Promise<void> {
const workingDirectory = getWorkingDirectory()
const experimental = core.getInput(`experimental`).split(`,`)
if (experimental.includes(`automatic-module-directories`)) {
const wds = modulesAutoDetection(workingDirectory)
const cwd = process.cwd()
for (const wd of wds) {
await core.group(`run golangci-lint in ${path.relative(cwd, wd)}`, () => runGolangciLint(binPath, wd))
}
return
}
await core.group(`run golangci-lint`, () => runGolangciLint(binPath, workingDirectory))
}
export async function run(): Promise<void> {
try {
const installOnly = core.getBooleanInput(`install-only`, { required: true })
await core.group(`Restore cache`, restoreCache)
const { binPath, patchPath } = await core.group(`prepare environment`, () => prepareEnv(installOnly))
const binPath = await core.group(`Install`, () => install().then(plugins.install))
core.addPath(path.dirname(binPath))
if (core.getInput(`debug`)) {
await core.group(`Debug`, () => debugAction(binPath))
}
const installOnly = core.getBooleanInput(`install-only`, { required: true })
if (installOnly) {
return
}
await core.group(`run golangci-lint`, () => runLint(binPath, patchPath))
await runLint(binPath)
} catch (error) {
core.error(`Failed to run: ${error}, ${error.stack}`)
core.setFailed(error.message)

View file

@ -67,6 +67,12 @@ const isLessVersion = (a: Version, b: Version): boolean => {
const getRequestedVersion = (): Version => {
let requestedVersion = core.getInput(`version`)
let versionFilePath = core.getInput(`version-file`)
if (requestedVersion && versionFilePath) {
core.warning(`Both version (${requestedVersion}) and version-file (${versionFilePath}) inputs are specified, only version will be used`)
}
const workingDirectory = core.getInput(`working-directory`)
let goMod = "go.mod"
@ -83,6 +89,27 @@ const getRequestedVersion = (): Version => {
}
}
if (requestedVersion == "" && versionFilePath) {
if (workingDirectory) {
versionFilePath = path.join(workingDirectory, versionFilePath)
}
if (!fs.existsSync(versionFilePath)) {
throw new Error(`The specified golangci-lint version file at: ${versionFilePath} does not exist`)
}
const content = fs.readFileSync(versionFilePath, "utf-8")
if (path.basename(versionFilePath) === ".tool-versions") {
// asdf/mise file.
const match = content.match(/^golangci-lint\s+([^\n#]+)/m)
requestedVersion = match ? "v" + match[1].trim().replace(/^v/gi, "") : ""
} else {
// .golangci-lint-version file.
requestedVersion = "v" + content.trim().replace(/^v/gi, "")
}
}
const parsedRequestedVersion = parseVersion(requestedVersion)
if (parsedRequestedVersion == null) {
return null