Summary
The Qlty Check job has never analyzed a single file. It passes on every PR because it
finds nothing to look at, not because there is nothing to find.
That takes down all three configured plugins — actionlint, trufflehog and
osv-scanner — plus the entire qlty smells pass. Separately, 7 of the entries in
.qlty/qlty.toml are silently discarded, including every exclusion pattern.
Two independent problems, same file/job, so they are worth fixing together.
A. The job analyzes zero files
From the Qlty Check job on PR #470:
Run qlty check
No modified files for checks were found on your branch.
✔ No issues
Run qlty smells
[0/3] 🔍 Analyzing vs. HEAD... 0.02s
[1/3] 👀 Checking structure of 0 files... 0.00s
[2/3] 🤔 Looking for duplication across 0 files... 0.00s
Cause. Both qlty check and qlty smells default to changed files only, resolved
against an upstream ref. actions/checkout puts the runner on refs/remotes/pull/N/merge
in detached HEAD:
HEAD is now at 548f026fa Merge ad9cea9e3... into 69f89e37e...
With no branch to compare against, qlty resolves the comparison to HEAD itself — where
the working tree is by definition unmodified — and the changed-file set is empty.
Note this is not a checkout problem: ci.yml:75
already sets fetch-depth: 0, so the base commit is present locally. qlty is simply never
told to use it.
Consequence. Since the job was added, qlty check has reported ✔ No issues on every
PR without running actionlint, trufflehog or osv-scanner even once. A green Qlty Check has
been carrying no signal.
B. Seven config entries are silently ignored
Printed as warnings on every run, in both steps:
WARNING: The `source.0.exclude_patterns` entry in qlty.toml is not part of the supported configuration and will be ignored.
WARNING: The `smells.?.file_length` entry in qlty.toml is not part of the supported configuration and will be ignored.
WARNING: The `smells.?.function_length` entry in qlty.toml is not part of the supported configuration and will be ignored.
WARNING: The `smells.?.large_class` entry in qlty.toml is not part of the supported configuration and will be ignored.
WARNING: The `smells.?.long_parameter_list` entry in qlty.toml is not part of the supported configuration and will be ignored.
WARNING: The `smells.?.cognitive_complexity` entry in qlty.toml is not part of the supported configuration and will be ignored.
WARNING: The `smells.?.duplicate_code` entry in qlty.toml is not part of the supported configuration and will be ignored.
B1 — exclude_patterns is nested under [[source]]
.qlty/qlty.toml:16-29:
[[source]]
name = "default"
default = true
# Exclusion patterns
exclude_patterns = [
"node_modules/**",
...
]
In TOML, a bare key after a [[table]] header belongs to that table — hence
source.0.exclude_patterns. The docs place
exclude_patterns at the top level. Moving the block above the [[source]] header
fixes it.
So node_modules/, dist/, build/ and coverage/ are currently not excluded from
analysis at all.
B2 — 6 of 9 smell names don't exist in qlty
qlty's supported smells are boolean_logic, nested_control_flow, function_parameters,
return_statements, file_complexity, function_complexity, identical_code,
similar_code.
Configured in qlty.toml |
Status |
Closest supported equivalent |
boolean_logic |
✅ applied |
— |
nested_control_flow |
✅ applied |
— |
function_parameters |
✅ applied |
— |
function_length |
❌ ignored |
no direct equivalent |
file_length |
❌ ignored |
file_complexity |
cognitive_complexity |
❌ ignored |
function_complexity |
duplicate_code |
❌ ignored |
identical_code / similar_code |
large_class |
❌ ignored |
no direct equivalent |
long_parameter_list |
❌ ignored |
duplicate of function_parameters |
[smells] mode = "block" is set, so once A is fixed these thresholds actually start
mattering.
Suggested fix
Fix B first — otherwise A turns the job red against unfiltered node_modules/ and
dist/ and with two thirds of the thresholds inert.
-
B1 — move exclude_patterns above the [[source]] block in .qlty/qlty.toml.
-
B2 — rename the 6 unsupported smell tables to qlty's names (or drop the ones with
no equivalent). Confirm the warnings are gone from the job log.
-
A — give both commands an explicit base. Both accept --all and
--upstream <ref>:
- name: Run qlty check
run: qlty check --upstream origin/${{ github.base_ref || 'main' }}
- name: Run qlty code smells analysis
run: qlty smells --upstream origin/${{ github.base_ref || 'main' }}
--all is the other option, but see the caveat.
Caveat
Expect the job to go red the first time it actually runs. This repo is a fork of
microsoft/vscode-jupyter with a large inherited src/, none of which has ever been
through actionlint, trufflehog, osv-scanner or a smells pass.
--upstream (changed files vs. the PR base) keeps the blast radius to code we are
actually touching and is the gentler path. --all would surface the entire inherited
backlog at once and probably needs a triage pass before it can gate merges.
timeout-minutes: 3 (ci.yml:69)
was set when the job did no work and will likely need raising.
How this surfaced
CodeRabbit flagged SC2012 (ls → find) on .github/workflows/e2e.yml in #470, on the
grounds that it "can fail workflow lint validation." Checking whether that was true
revealed that actionlint is configured but has never inspected a workflow file.
Related
Linear BLU-6280
is a separate actionlint problem in deepnote-internal (config file at the repo root
where actionlint never loads it). Different repo, different cause — noted only because
both add up to "actionlint has not been running anywhere."
Summary
The
Qlty Checkjob has never analyzed a single file. It passes on every PR because itfinds nothing to look at, not because there is nothing to find.
That takes down all three configured plugins — actionlint, trufflehog and
osv-scanner — plus the entire
qlty smellspass. Separately, 7 of the entries in.qlty/qlty.tomlare silently discarded, including every exclusion pattern.Two independent problems, same file/job, so they are worth fixing together.
A. The job analyzes zero files
From the
Qlty Checkjob on PR #470:Cause. Both
qlty checkandqlty smellsdefault to changed files only, resolvedagainst an upstream ref.
actions/checkoutputs the runner onrefs/remotes/pull/N/mergein detached HEAD:
With no branch to compare against, qlty resolves the comparison to
HEADitself — wherethe working tree is by definition unmodified — and the changed-file set is empty.
Note this is not a checkout problem:
ci.yml:75already sets
fetch-depth: 0, so the base commit is present locally. qlty is simply nevertold to use it.
Consequence. Since the job was added,
qlty checkhas reported✔ No issueson everyPR without running actionlint, trufflehog or osv-scanner even once. A green Qlty Check has
been carrying no signal.
B. Seven config entries are silently ignored
Printed as warnings on every run, in both steps:
B1 —
exclude_patternsis nested under[[source]].qlty/qlty.toml:16-29:In TOML, a bare key after a
[[table]]header belongs to that table — hencesource.0.exclude_patterns. The docs placeexclude_patternsat the top level. Moving the block above the[[source]]headerfixes it.
So
node_modules/,dist/,build/andcoverage/are currently not excluded fromanalysis at all.
B2 — 6 of 9 smell names don't exist in qlty
qlty's supported smells are
boolean_logic,nested_control_flow,function_parameters,return_statements,file_complexity,function_complexity,identical_code,similar_code.qlty.tomlboolean_logicnested_control_flowfunction_parametersfunction_lengthfile_lengthfile_complexitycognitive_complexityfunction_complexityduplicate_codeidentical_code/similar_codelarge_classlong_parameter_listfunction_parameters[smells] mode = "block"is set, so once A is fixed these thresholds actually startmattering.
Suggested fix
Fix B first — otherwise A turns the job red against unfiltered
node_modules/anddist/and with two thirds of the thresholds inert.B1 — move
exclude_patternsabove the[[source]]block in.qlty/qlty.toml.B2 — rename the 6 unsupported smell tables to qlty's names (or drop the ones with
no equivalent). Confirm the warnings are gone from the job log.
A — give both commands an explicit base. Both accept
--alland--upstream <ref>:--allis the other option, but see the caveat.Caveat
Expect the job to go red the first time it actually runs. This repo is a fork of
microsoft/vscode-jupyterwith a large inheritedsrc/, none of which has ever beenthrough actionlint, trufflehog, osv-scanner or a smells pass.
--upstream(changed files vs. the PR base) keeps the blast radius to code we areactually touching and is the gentler path.
--allwould surface the entire inheritedbacklog at once and probably needs a triage pass before it can gate merges.
timeout-minutes: 3(ci.yml:69)was set when the job did no work and will likely need raising.
How this surfaced
CodeRabbit flagged SC2012 (
ls→find) on.github/workflows/e2e.ymlin #470, on thegrounds that it "can fail workflow lint validation." Checking whether that was true
revealed that actionlint is configured but has never inspected a workflow file.
Related
Linear BLU-6280
is a separate actionlint problem in
deepnote-internal(config file at the repo rootwhere actionlint never loads it). Different repo, different cause — noted only because
both add up to "actionlint has not been running anywhere."