The Debian Janitor is an automated system that commits fixes for (minor) issues in Debian packages that can be fixed by software. It gradually started proposing merges in early December. The first set of changes sent out ran lintian-brush on sid packages maintained in Git. This post is part of a series about the progress of the Janitor.
Scheduling Lintian Fixes
To determine which packages to process, the Janitor looks at the import of lintian output across the archive that is available in UDD [1]. It will prioritize those packages with the most and more severe issues that it has fixers for.
Once a package is selected, it will clone the packaging repository and run lintian-brush on it. Lintian-brush provides a framework for applying a set of “fixers” to a package. It will run each of a set of “fixers” in a pristine version of the repository, and handles most of the heavy lifting.
The Inner Workings of a Fixer
Each fixer is just an executable which gets run in a clean checkout of the package, and can make changes there. Most of the fixers are written in Python or shell, but they can be in any language.
The contract for fixers is pretty simple:
- If the fixer exits with non-zero, the changes are reverted and fixer is considered to have failed
- If it exits with zero and made changes, then it should write a summary of its changes to standard out
If a fixer is uncertain about the changes it has made, it should report so on standard output using a pseudo-header. By default, lintian-brush will discard any changes with uncertainty but if you are running it locally you can still apply them by specifying --uncertain.
The summary message on standard out will be used for the commit message and (possibly) the changelog message, if the package doesn’t use gbp dch.
Example Fixer
Let’s look at an example. The package priority “extra” is deprecated since Debian Policy 4.0.1 (released August 2 017) – see Policy 2.5 “Priorities”. Instead, most packages should use the “optional” priority.
Lintian will warn when a package uses the deprecated “extra” value for the “Priority” - the associated tag is priority-extra-is-replaced-by-priority-optional. Lintian-brush has a fixer script that can automatically replace “extra” with “optional”.
On systems that have lintian-brush installed, the source for the fixer lives in /usr/share/lintian-brush/fixers/priority-extra-is-replaced-by-priority-optional.py, but here is a copy of it for reference:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/python3 from debmutate.control import ControlEditor from lintian_brush.fixer import report_result, fixed_lintian_tag with ControlEditor() as updater: for para in updater.paragraphs: if para.get("Priority") == "extra": para["Priority"] = "optional" fixed_lintian_tag( para, 'priority-extra-is-replaced-by-priority-optional') report_result("Change priority extra to priority optional.") |
This fixer is written in Python and uses the debmutate library to easily modify control files while preserving formatting — or back out if it is not possible to preserve formatting.
All the current fixers come with tests, e.g. for this particular fixer the tests can be found here: https://salsa.debian.org/jelmer/lintian-brush/-/tree/master/tests/priority-extra-is-replaced-by-priority-optional.
For more details on writing new fixers, see the README for lintian-brush.
For more details on debugging them, see the manual page.
Successes by fixer
Here is a list of the fixers currently available, with the number of successful merges/pushes per fixer:
Footnotes
[1] | temporarily unavailable due to Debian bug #960156 – but the Janitor is relying on historical data |
For more information about the Janitor’s lintian-fixes efforts, see the landing page.