Files
github-action/wiki/QualityChecks.md
T
Tirsvad 820f05c0bd
Validate workflows / validate (pull_request) Successful in 16s
Add the guide for reading quality-check results
Explain how to call the shared quality-checks workflow, read a failed run,
fix the typical findings of ruff, mypy, shellcheck and shfmt, reproduce a
run locally and configure the tools through the project's own files,
including the shfmt .editorconfig route found in the RepoFoundry trial.
Add the QualityChecks wiki page with its Danish and Bahasa Malaysia
translations, update the capability row and teach build_wiki.py the page.

Task: MIL-003#5
2026-10-10 20:25:52 +08:00

4.7 KiB

This page is generated from guides/quality-checks.md. Changes made here are overwritten the next time the wiki is published.

English | Dansk | Bahasa Melayu

Reading quality-check results

How a software engineer calls the shared quality checks, reads a failed run and makes it pass. The workflow lints and format-checks the Python and shell files of a repository with pinned tools, changes no file and needs no secret. Its contract is ADR-0005 in this repository.

Calling the workflow

name: Quality

on:
  pull_request:
  push:
    branches: [ main ]

jobs:
  quality:
    permissions:
      contents: read
    uses: TirSystem/github-action/.gitea/workflows/quality-checks.yml@main
    with:
      languages: python,shell
Input Default Meaning
languages python,shell Comma list of the languages to check
working-directory . Directory, relative to the repository root, whose files are checked
ruff-version 0.6.9 Version of ruff
mypy-version 1.11.2 Version of mypy
shellcheck-py-version 0.10.0.1 Version of the shellcheck-py package (ShellCheck 0.10.0)
shfmt-py-version 3.11.0.2 Version of the shfmt-py package (shfmt 3.11.0)

Reference the workflow at main or at a tag, never at the branch of a pull request: that branch is deleted when the pull request is merged and the reference stops working.

What is checked

Language Files Tools
Python tracked *.py under the working directory ruff check, ruff format --check, mypy --strict
Shell tracked *.sh under the working directory shellcheck, shfmt -d

Untracked files are not checked. A language without files is skipped with a notice and counts as a pass. Project tests are not run.

Reading a run

  1. Open the status check on the pull request, then the job quality-checks.
  2. Each tool has its own log group named after it. Every tool runs even when an earlier one failed, so one run shows all findings.
  3. A tool ends with PASS <tool> or FAIL <tool>. The last line of a failed run names the tools that failed: Quality checks failed: ruff check shellcheck.
  4. A finding is written by the tool itself as path:line:column: CODE message. Paths are relative to working-directory.

Typical failures and fixes

Tool What the log shows Fix
ruff check F401 ... imported but unused Remove the import, or use it
ruff format --check Would reformat: <file> Run ruff format <file> and commit
mypy --strict Function is missing a type annotation Add parameter and return types
shellcheck SC2086 ... Double quote to prevent globbing Quote the expansion: "$1"
shfmt -d a diff of <file>.orig and <file> Run shfmt -w <file> with the project's options and commit

To reproduce a run on your machine, install the same versions and run the commands of the table:

python3 -m venv .qc
.qc/bin/pip install ruff==0.6.9 mypy==1.11.2 shellcheck-py==0.10.0.1 shfmt-py==3.11.0.2
.qc/bin/ruff check . && .qc/bin/ruff format --check .

Configuring the tools

The workflow adds no configuration; it runs from the repository root, so the files of the project apply:

Tool File Example
ruff pyproject.toml [tool.ruff] with line-length = 100
mypy pyproject.toml [tool.mypy] with per-module ignore_missing_imports
shellcheck .shellcheckrc external-sources=true and source-path=SCRIPTDIR
shfmt .editorconfig [*.sh] with indent_size = 2 and switch_case_indent = true

shfmt follows a project's style only through .editorconfig. A shell project that formats with its own flags (for example shfmt -i 2 -ci) should expect a first formatting failure and express the flags there; in the first adoption (RepoFoundry) one line, switch_case_indent = true, was enough and no script changed.

When the workflow itself fails

Message Cause Fix
[configuration] Unknown language '<x>' languages has a value other than python or shell Correct the input
[configuration] working-directory must be a relative path inside the repository. An absolute path or .. Use a path inside the repository
[configuration] working-directory '<x>' does not exist. The directory is not in the repository Correct the input
The install step fails PyPI or the runner network is unreachable Re-run the job; see troubleshooting.md