Skip to content

qlty check analyzes 0 files in CI, so actionlint, trufflehog and osv-scanner have never run #480

Description

@tkislan

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.

  1. B1 — move exclude_patterns above the [[source]] block in .qlty/qlty.toml.

  2. 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.

  3. 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 (lsfind) 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."

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions