5.2 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@v1
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) |
tools-ref |
v1 |
Tag or branch of TirSystem/github-action from which the script tools/quality-checks.sh is fetched |
Reference the workflow at the major tag (@v1) or at an exact tag
(@v1.0.0), never at main and never at the branch of a pull request: that
branch is deleted when the pull request is merged and the reference stops
working. See the upgrade guide for what each choice receives.
The workflow file calls a script of this repository, fetched at tools-ref. A
call at an exact tag is pinned completely only when tools-ref names the same
tag, for example @v1.0.1 with tools-ref: v1.0.1; with the default the
script follows v1.
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
- Open the status check on the pull request, then the job
quality-checks. - 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.
- A tool ends with
PASS <tool>orFAIL <tool>. The last line of a failed run names the tools that failed:Quality checks failed: ruff check shellcheck. - A finding is written by the tool itself as
path:line:column: CODE message. Paths are relative toworking-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 |