-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite Bugalint as a GitHub Action (#13)
- Loading branch information
Showing
30 changed files
with
11,387 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
env: | ||
node: true | ||
es6: true | ||
jest: true | ||
extends: | ||
- standard-with-typescript | ||
- plugin:jest/recommended | ||
- plugin:github/recommended | ||
overrides: | ||
- files: ['*.js', '*.jsx', '*.ts', '*.tsx'] | ||
ignorePatterns: | ||
- '**/dist/*' | ||
- 'jest.config.js' | ||
parserOptions: | ||
ecmaVersion: latest | ||
sourceType: module | ||
project: | ||
- './tsconfig.json' | ||
- './__tests__/tsconfig.json' | ||
plugins: | ||
- jest | ||
rules: | ||
'i18n-text/no-en': 'off' | ||
'@typescript-eslint/space-before-function-paren': 'off' | ||
'generator-star-spacing': 'off' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
version: 2 | ||
updates: | ||
- package-ecosystem: github-actions | ||
directory: / | ||
labels: | ||
- dependabot | ||
- actions | ||
schedule: | ||
interval: daily | ||
- package-ecosystem: npm | ||
directory: / | ||
labels: | ||
- dependabot | ||
- npm | ||
schedule: | ||
interval: daily |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
name: Lint | ||
|
||
on: [pull_request] | ||
|
||
jobs: | ||
eslint: | ||
name: ESLint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Install Dependencies | ||
run: npm clean-install; npm install @microsoft/eslint-formatter-sarif | ||
- name: Run ESLint | ||
run: npx eslint . --format @microsoft/eslint-formatter-sarif --output-file lint.sarif | ||
- name: Upload analysis results to GitHub | ||
uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
with: | ||
sarif_file: lint.sarif | ||
markdownlint: | ||
name: markdownlint | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Lint | ||
uses: avto-dev/markdown-lint@v1 | ||
with: | ||
args: '**/*.md' | ||
output: 'lint.txt' | ||
config: '.mdl.yml' | ||
- name: Convert | ||
uses: ./ | ||
if: always() | ||
with: | ||
inputFile: 'lint.txt' | ||
toolName: 'mdl' | ||
inputFormat: 'mdl' | ||
verbose: 'true' | ||
- name: Upload results | ||
uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
with: | ||
sarif_file: sarif.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
name: Test | ||
|
||
on: [pull_request] | ||
|
||
jobs: | ||
check-dist: | ||
name: Check dist/ | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Install Dependencies | ||
run: npm clean-install | ||
- name: Build dist/ Directory | ||
run: npm run package | ||
- name: Compare Expected and Actual Directories | ||
id: diff | ||
run: | | ||
if [ "$(git diff --ignore-space-at-eol --text dist/ | wc -l)" -gt "0" ]; then | ||
echo "Detected uncommitted changes after build. See status below:" | ||
git diff --ignore-space-at-eol --text dist/ | ||
exit 1 | ||
fi | ||
- uses: actions/upload-artifact@v3 | ||
if: ${{ failure() && steps.diff.conclusion == 'failure' }} | ||
with: | ||
name: dist | ||
path: dist/ | ||
jest: | ||
name: Jest | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Install Package | ||
run: npm clean-install | ||
- name: Run Jest | ||
run: npm run test | ||
gha: | ||
name: GitHub Action | ||
runs-on: ubuntu-latest | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
run: | ||
[ | ||
{ linter: 'flake8', format: 'flake8', regex: '', levelMap: '' }, | ||
{ linter: 'mypy', format: 'mypy', regex: '', levelMap: '' }, | ||
{ linter: 'pylint', format: 'pylint', regex: '', levelMap: '' }, | ||
{ linter: 'mdl', format: 'mdl', regex: '', levelMap: '' }, | ||
{ | ||
linter: 'custom', | ||
format: '', | ||
regex: '^(?<path>[^-\n]+)(?:-(?<line>\d+))?(?:-(?<col>\d+))?(?:-(?<eline>\d+))?(?:-(?<ecol>\d+))? (?<level>[^:\s]+):(?<id>[^:\s]+):(?<sym>[^:\s]+) (?<msg>.+)$', | ||
levelMap: '{ "err": "error", "warn": "warning", "info": "note" }' | ||
} | ||
] | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Install Dependencies | ||
run: npm install -g json-diff | ||
- name: Run Action | ||
uses: ./ | ||
with: | ||
inputFile: '__tests__/${{ matrix.run.linter }}.input.txt' | ||
toolName: 'test' | ||
inputFormat: ${{ matrix.run.format }} | ||
inputRegex: ${{ matrix.run.regex }} | ||
levelMap: ${{ matrix.run.levelMap }} | ||
verbose: 'true' | ||
- name: Create Diff | ||
run: json-diff "__tests__/${{ matrix.run.linter }}.output.json" "sarif.json" | tee diff.txt | ||
- name: Test Output | ||
run: | | ||
if [ -s diff.txt ]; | ||
then | ||
echo "Failed with diff:" | ||
cat diff.txt | ||
exit 1 | ||
else | ||
echo "Success" | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# MD013/line-length - Line length | ||
MD013: | ||
line_length: 160 | ||
ignore_code_blocks: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"printWidth": 160, | ||
"singleQuote": true, | ||
"trailingComma": "none", | ||
"semi": false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"editor.defaultFormatter": "esbenp.prettier-vscode", | ||
"editor.formatOnSave": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2021 Bugale Bugalit | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
# Bugalint | ||
|
||
This GitHub Action converts various linter outputs to SARIF, and supports custom linter output formats using regular expressions. | ||
This action can be used in conjunction with | ||
[GitHub's Code Scanning feature](https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/about-code-scanning) to | ||
[report linter issues as code scanning alerts](#basic-example). | ||
|
||
## Usage | ||
|
||
### Basic Example | ||
|
||
This is a basic example of a GitHub Workflow that uses this action to run [pylint](https://github.com/pylint-dev/pylint) and report its issues as code scanning alerts: | ||
|
||
```yaml | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-python@v4 | ||
- run: pip install pylint | ||
- run: pylint --output-format=json my_python_file.py > lint.txt | ||
- uses: bugale/bugalint@v1 | ||
if: always() | ||
with: | ||
inputFile: lint.txt | ||
toolName: pylint | ||
inputFormat: pylint | ||
- uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
with: | ||
sarif_file: sarif.json | ||
``` | ||
### Input Parameters | ||
- `inputFile`: _(required)_ The path to the input file, i.e. the file containing the output of the linter. | ||
|
||
- `outputFile`: The path to the output SARIF file this action should generate. If not specified, the action will generate a `sarif.json` file in the root of | ||
the repository. | ||
|
||
- `toolName`: _(required)_ The `tool name` that will be written in the SARIF output. This is required per SARIF's schema. | ||
|
||
- `inputFormat`: The name of a linter output format that this action [natively supports](#natively-supported-linter-output-formats). If not specified, the | ||
action will expect `inputRegex` input to be specified. | ||
|
||
- `inputRegex`: The [JS-style regular expression to parse the input file](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions). | ||
It should include [named groups for the different issues' metadata](#input-regex-named-groups). If not specified, the action will expect `inputFormat` input | ||
to be specified. | ||
|
||
- `levelMap`: An optional JSON object mapping between the linter's levels and the SARIF levels (`note`/`warning`/`error`). Ignored unless `inputRegex` is | ||
specified. | ||
|
||
- `verbose`: Causes the action to print it's input and output. Useful for debugging. | ||
|
||
#### Natively Supported Linter Output Formats | ||
|
||
This action supports a bunch of linter output formats, for which no `inputRegex` is required: | ||
|
||
- `pylint`: The format of [pylint](https://github.com/pylint-dev/pylint) linter's JSON output (requires using `--output-format=json` in pylint's command line). | ||
|
||
- `flake8`: The format of [flake8](https://github.com/PyCQA/flake8) linter's default output. | ||
|
||
- `mypy`: The format of [mypy](https://github.com/python/mypy) linter's default output. It is possible and recommended to pass `--show-column-numbers` and | ||
`--show-error-end` in mypy's command line to have the richest SARIF. | ||
|
||
- `markdownlint`: The format of [markdownlint](https://github.com/markdownlint/markdownlint) linter's default output. | ||
|
||
#### Input Regex Named Groups | ||
|
||
When using a custom regular expression, it must contains named groups for Bugalint to successfully understand which parts of each line are the issue's | ||
metadata. Most of the named groups are optional. | ||
|
||
The supported named groups are: | ||
|
||
- `msg`: _(required)_ The message. Required by the SARIF schema. | ||
|
||
- `id`: A unique identifier of the rule by which the issue was generated. Example: `E123` | ||
|
||
- `sym`: A unique human-readable identifier of the rule by which the issue was generated. Example: `no-unused-import` | ||
|
||
- `level`: The level of this issue. Should be one of `error`/`warning`/`note`. If the linter uses different levels, you can use the `levelMap` input to map | ||
between the linter's levels and the SARIF levels. | ||
|
||
- `path`: The path of the file on which the issue was reported. Example: `src/my_python_file.py` | ||
|
||
- `line`: The line on which the issue was reported. | ||
|
||
- `col`: The column on which the issue was reported. | ||
|
||
- `eline`: The end line on which the issue was reported. | ||
|
||
- `ecol`: The end column on which the issue was reported. | ||
|
||
### Example With Custom Regex | ||
|
||
This is an example of how this action can be used to parse the output of a hypothetical custom linter called `mylinter`, which outputs issues in the following | ||
format: | ||
|
||
```text | ||
test.py-3-1-4-10 info:N123:some-note Message 1 | ||
test.py-3-1 warn:E124:some-warning Message 2 | ||
test.py err:E125:some-error Message 3 | ||
Finished running | ||
``` | ||
|
||
```yaml | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-python@v4 | ||
- run: pip install mylinter | ||
- run: mylinter test.py > lint.txt | ||
- uses: bugale/bugalint@v1 | ||
if: always() | ||
with: | ||
inputFile: lint.txt | ||
toolName: mylinter | ||
inputRegex: '^(?<path>[^-\n]+)(?:-(?<line>\d+))?(?:-(?<col>\d+))?(?:-(?<eline>\d+))?(?:-(?<ecol>\d+))? (?<level>[^:\s]+):(?<id>[^:\s]+):(?<sym>[^:\s]+) (?<msg>.+)$' | ||
levelMap: '{ "err": "error", "warn": "warning", "info": "note" }' | ||
- uses: github/codeql-action/upload-sarif@v2 | ||
if: always() | ||
with: | ||
sarif_file: sarif.json | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import '@microsoft/jest-sarif' | ||
import { readFileSync } from 'fs' | ||
import { convert, getKnownParser, getRegexParser, type Parser } from '../src/bugalint' | ||
|
||
describe('fullConversion', () => { | ||
it.each([ | ||
['mypy', undefined], | ||
['pylint', undefined], | ||
['flake8', undefined], | ||
['mdl', undefined], | ||
[ | ||
'custom', | ||
getRegexParser( | ||
/^(?<path>[^-\n]+)(?:-(?<line>\d+))?(?:-(?<col>\d+))?(?:-(?<eline>\d+))?(?:-(?<ecol>\d+))? (?<level>[^:\s]+):(?<id>[^:\s]+):(?<sym>[^:\s]+) (?<msg>.+)$/gm, | ||
{ err: 'error', warn: 'warning', info: 'note' } | ||
) | ||
] | ||
])('%s', (name: string, parser?: Parser) => { | ||
const input = readFileSync(`__tests__/${name}.input.txt`, 'utf-8') | ||
const output = readFileSync(`__tests__/${name}.output.json`, 'utf-8') | ||
const result = convert(parser ?? getKnownParser(name), input, 'test') | ||
expect(result).toBeValidSarifLog() | ||
expect(JSON.parse(JSON.stringify(result))).toStrictEqual(JSON.parse(output)) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
test.py-3-1-4-10 info:N123:some-note Message 1 | ||
test.py-3-1 warn:E124:some-warning Message 2 | ||
test.py err:E125:some-error Message 3 | ||
Finished running |
Oops, something went wrong.