reviewdog
Plumb does not ship a built-in reviewdog formatter. The integration
here converts plumb lint --format json output to reviewdog’s
rdjson format with jq.
The committed runner config lives at contrib/reviewdog-plumb.yaml in
the Plumb repo. Copy it into your own project’s contrib/ directory
and replace the plumb-fake://hello placeholder with the URL you want
to lint before passing -conf=contrib/reviewdog-plumb.yaml to
reviewdog.
What the config does
Plumb reports findings against a rendered target, not a source file in
your repository. reviewdog expects file-based diagnostics. The config
committed in contrib/reviewdog-plumb.yaml does four things:
- running
plumb lint plumb-fake://hello --format json(replaceplumb-fake://hellowith the URL you want to lint); - converting
.violations[]tordjson; - attaching each diagnostic to the synthetic path
plumb-lint-target:1:1; - keeping the rule id, docs URL, selector, viewport, and message.
That makes the output usable for reviewdog reporters such as
local, github-check, and github-annotations. It is a transport
layer, not source mapping.
Local run
reviewdog \
-conf=contrib/reviewdog-plumb.yaml \
-runners=plumb \
-reporter=local \
-filter-mode=nofilter
GitHub Actions example
name: plumb-reviewdog
on:
pull_request:
permissions:
contents: read
checks: write
jobs:
plumb:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Plumb
run: cargo install plumb-cli
- uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
- name: Run reviewdog
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
reviewdog \
-conf=contrib/reviewdog-plumb.yaml \
-runners=plumb \
-reporter=github-check \
-filter-mode=nofilter
The JSON pipeline
The runner config uses this exact pipeline. Replace plumb-fake://hello
with the real target URL in your copied config.
plumb lint plumb-fake://hello --format json | jq -c '
{
source: {
name: "plumb",
url: "https://plumb.aramhammoudeh.com"
},
diagnostics: [
.violations[] | {
message: (
.message
+ " selector=" + (.selector // "<unknown>")
+ " viewport=" + (.viewport // "<unknown>")
),
location: {
path: "plumb-lint-target",
range: {
start: {
line: 1,
column: 1
}
}
},
severity: (
if .severity == "error" then "ERROR"
elif .severity == "warning" then "WARNING"
else "INFO"
end
),
code: {
value: .rule_id,
url: .doc_url
}
}
]
}
'
On the current plumb-fake://hello fixture, plumb lint exits 3
because it found a warning. The config still works because the runner
command is a plain shell pipeline, so the pipeline exit status comes
from jq, which exits 0 after producing valid rdjson. If you wrap
the same pipeline in a shell that enables pipefail, capture or ignore
Plumb’s exit code yourself before handing the transformed JSON to
reviewdog.
Limits
- The synthetic
plumb-lint-targetpath is intentional. Plumb is linting rendered output, so there is no source file or source line to report. - If you need GitHub Security alerts, use the SARIF workflow from GitHub Code Scanning instead.