Skip to content

Commit 9dab1a2

Browse files
caugnerLeoMcA
andauthored
ci(workflows): suggest lint fixes on PRs via reviewdog (#29423)
Adds a new `pr-reviewdog` workflow that automatically suggests lint fixes when the test lint job fails. The workflow captures fix diffs as artifacts and posts inline suggestions and a sticky PR comment with a deep-link to the lint job logs. Includes documentation for contributors on how to apply the suggestions. Co-authored-by: Leo McArdle <leo@mozilla.com>
1 parent fe83c72 commit 9dab1a2

3 files changed

Lines changed: 176 additions & 1 deletion

File tree

.github/workflows/pr-reviewdog.yml

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
name: PR Reviewdog
2+
3+
on:
4+
workflow_run:
5+
workflows:
6+
- "Test"
7+
types:
8+
- completed
9+
branches-ignore:
10+
- main
11+
12+
permissions:
13+
# Download artifact from lint workflow.
14+
actions: read
15+
# Post inline review comments via reviewdog.
16+
pull-requests: write
17+
# Report commit status.
18+
statuses: write
19+
20+
jobs:
21+
reviewdog:
22+
runs-on: ubuntu-latest
23+
env:
24+
STATUS_PATH: repos/${{ github.repository }}/statuses/${{ github.event.workflow_run.head_sha }}
25+
STATUS_CONTEXT: ${{ github.workflow }}
26+
STATUS_TARGET: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
27+
steps:
28+
- name: Mark status as pending
29+
env:
30+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31+
run: |
32+
gh api "$STATUS_PATH" \
33+
-f state=pending \
34+
-f context="$STATUS_CONTEXT" \
35+
-f description='Running' \
36+
-f target_url="$STATUS_TARGET"
37+
38+
- name: Identify PR
39+
id: identify-pr
40+
env:
41+
BASE_REPO: ${{ github.repository }}
42+
GITHUB_TOKEN: ${{ github.token }}
43+
HEAD_REPO: ${{ github.event.workflow_run.head_repository.full_name }}
44+
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
45+
run: |
46+
PR_NUMBER=$(gh api "repos/$HEAD_REPO/commits/$HEAD_SHA/pulls" \
47+
--jq ".[] | select(.base.repo.full_name == \"$BASE_REPO\") | .number")
48+
echo "number=$PR_NUMBER" >> $GITHUB_OUTPUT
49+
50+
- name: Download artifact
51+
if: steps.identify-pr.outputs.number
52+
continue-on-error: true
53+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
54+
with:
55+
name: lint-results
56+
path: lint-results
57+
github-token: ${{ secrets.GITHUB_TOKEN }}
58+
run-id: ${{ github.event.workflow_run.id }}
59+
60+
- name: Check for artifact
61+
id: check
62+
if: steps.identify-pr.outputs.number && hashFiles('lint-results/') != ''
63+
run: echo "HAS_ARTIFACT=true" >> "$GITHUB_OUTPUT"
64+
65+
- name: Checkout
66+
if: steps.identify-pr.outputs.number
67+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
68+
with:
69+
path: browser-compat-data
70+
ref: main
71+
persist-credentials: false
72+
73+
- name: Setup reviewdog
74+
if: steps.check.outputs.HAS_ARTIFACT == 'true'
75+
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f # v1.5.0
76+
with:
77+
reviewdog_version: v0.21.0
78+
79+
- name: Add PR review with suggested changes using `git diff` output
80+
if: steps.check.outputs.HAS_ARTIFACT == 'true' && hashFiles('lint-results/lint.diff') != ''
81+
working-directory: browser-compat-data
82+
env:
83+
CI_PULL_REQUEST: ${{ steps.identify-pr.outputs.number }}
84+
CI_COMMIT: ${{ github.event.workflow_run.head_sha }}
85+
CI_REPO_OWNER: ${{ github.repository_owner }}
86+
CI_REPO_NAME: ${{ github.event.repository.name }}
87+
CI_BRANCH: ${{ github.event.workflow_run.head_branch }}
88+
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
89+
run: |
90+
env -u GITHUB_ACTIONS reviewdog \
91+
-guess \
92+
-name="bcd-linter" \
93+
-f=diff \
94+
-f.diff.strip=1 \
95+
-filter-mode=diff_context \
96+
-reporter=github-pr-review < ../lint-results/lint.diff
97+
98+
- name: Post or update PR comment with context
99+
if: steps.check.outputs.HAS_ARTIFACT == 'true' && hashFiles('lint-results/lint.diff') != ''
100+
env:
101+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
102+
REPO: ${{ github.repository }}
103+
PR_NUMBER: ${{ steps.identify-pr.outputs.number }}
104+
TEST_RUN_ID: ${{ github.event.workflow_run.id }}
105+
TEST_RUN_URL: ${{ github.event.workflow_run.html_url }}
106+
run: |
107+
LINT_JOB_URL=$(gh api --paginate "repos/$REPO/actions/runs/$TEST_RUN_ID/jobs" \
108+
--jq '.jobs[] | select(.name == "lint") | .html_url' | head -1)
109+
LINT_JOB_URL=${LINT_JOB_URL:-$TEST_RUN_URL}
110+
111+
BODY="<!-- bcd-reviewdog -->
112+
The [lint check]($LINT_JOB_URL) found auto-fixable issues. Apply suggested changes (attributed to \`bcd-linter\`), or to fix all at once, run \`npm run lint:fix\` locally.
113+
114+
See also: [Automated lint suggestions on pull requests](https://github.com/$REPO/blob/main/docs/testing.md#automated-lint-suggestions-on-pull-requests)"
115+
116+
COMMENT_ID=$(gh api --paginate "repos/$REPO/issues/$PR_NUMBER/comments" \
117+
--jq '.[] | select(.user.login == "github-actions[bot]" and (.body | startswith("<!-- bcd-reviewdog -->"))) | .id' | head -1)
118+
119+
if [ -n "$COMMENT_ID" ]; then
120+
gh api -X PATCH "repos/$REPO/issues/comments/$COMMENT_ID" -f body="$BODY"
121+
else
122+
gh api "repos/$REPO/issues/$PR_NUMBER/comments" -f body="$BODY"
123+
fi
124+
125+
- name: Mark status as success
126+
if: success()
127+
env:
128+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
129+
run: |
130+
gh api "$STATUS_PATH" \
131+
-f state=success \
132+
-f context="$STATUS_CONTEXT" \
133+
-f description='Successful' \
134+
-f target_url="$STATUS_TARGET"
135+
136+
- name: Mark status as failure
137+
if: failure()
138+
env:
139+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
140+
run: |
141+
gh api "$STATUS_PATH" \
142+
-f state=failure \
143+
-f context="$STATUS_CONTEXT" \
144+
-f description='Failing' \
145+
-f target_url="$STATUS_TARGET"

.github/workflows/test.yml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,31 @@ jobs:
5555

5656
- run: npm ci
5757

58-
- run: npm run lint -- --fail-on-warnings
58+
- name: Lint
59+
id: lint
60+
run: npm run lint -- --fail-on-warnings
61+
62+
- name: Fix lint issues
63+
id: lint-fix
64+
if: failure() && steps.lint.conclusion == 'failure'
65+
run: |
66+
npm run lint:fix
67+
if [[ -n $(git diff) ]]; then
68+
echo "files_modified=true" >> "$GITHUB_OUTPUT"
69+
fi
70+
71+
- name: Collect artifact files
72+
if: failure() && steps.lint-fix.outputs.files_modified == 'true'
73+
run: |
74+
mkdir -p lint-results
75+
git diff > lint-results/lint.diff
76+
77+
- name: Upload artifact
78+
if: failure() && steps.lint-fix.outputs.files_modified == 'true'
79+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
80+
with:
81+
name: lint-results
82+
path: lint-results
5983

6084
test:
6185
runs-on: ubuntu-latest

docs/testing.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ For more information on the schema for feature data, see [`compat-data-schema.md
2222

2323
For more information on the schema for browser data, see [`browsers-schema.md`](../schemas/browsers-schema.md) and [`browsers.schema.json`](../schemas/browsers.schema.json).
2424

25+
## Automated lint suggestions on pull requests
26+
27+
When the lint check fails on a pull request, CI runs `npm run lint:fix` and posts the auto-fixable changes as inline review suggestions, attributed to `bcd-linter`. You can accept individual suggestions through GitHub's review UI, or apply all of them at once by running `npm run lint:fix` locally and committing the result.
28+
29+
If a suggestion looks wrong (for example, the linter is reporting a false positive), reply on the suggestion explaining why — a maintainer can help.
30+
2531
## Generate statistics
2632

2733
To see how changes will affect the statistics of exact (formerly "real") and ranged values, you can run `npm run stats [folder]`. This generates a Markdown-formatted table of the percentages of exact and ranged values for the eight primary browsers that browser-compat-data is focusing on. The script also takes an optional argument regarding a specific folder (such as `api` or `javascript`), which will print statistics result for only that folder. Additionally, you can run the script with `--all` to get statistics for all browsers tracked in BCD, not just the primary eight.

0 commit comments

Comments
 (0)