Metadata-Version: 2.1
Name: alidistlint
Version: 1.1.0
Summary: A code linter for alidist packages
Author-email: Timo Wilken <timo.wilken@cern.ch>
Project-URL: Homepage, https://github.com/TimoWilken/alidistlint
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: linters
License-File: LICENSE

# `alidistlint` - code linter for [alidist][] recipes

`alidistlint` runs [shellcheck][] on the scripts in [alidist][] recipes and [yamllint][] on their YAML headers, in addition to its own validation and checks on the YAML header.

## Usage

Run `alidistlint -h` to get more information about its arguments.

```
usage: alidistlint [-h] [-S] [-Y] [-H] [-f FORMAT] RECIPE [RECIPE ...]
```

You can disable individual checkers using `-S`/`--no-shellcheck`, `-Y`/`--no-yamllint` and `-H`/`--no-headerlint` (internal YAML header linting).
By default, all checkers are run.

Optionally, select the output format of errors using `-f`/`--format`.

Finally, pass one or multiple files to be checked to `alidistlint`. You can use `-` for the standard input here.

Errors and warnings will be printed to standard output in the format you selected.

If any messages with "error" severity were produced, `alidistlint` exits with a non-zero exit code.

## Shellcheck validation

The main build recipe (after the `---` line) is passed to `shellcheck`.

Currently, toplevel keys ending in `_recipe` or `_check` (such as `incremental_recipe`) are also checked using `shellcheck`.
This does not work for such keys specified in `overrides` yet.

There is a known issue with the checking of the above keys: if they do not start on a new line (using e.g. `key: |`), the reported line numbers for shellcheck errors will be off by one.

## Internal YAML header validation

The following error codes are produced by the internal linter (which can be switched off using `-H`/`--no-headerlint`).
There is currently no way to disable individual checks.

- `ali:empty`: The YAML header was not found.
  It must be terminated by a `\n`-terminated line containing nothing but three dashes (`---`).
- `ali:parse`: The YAML header could not be parsed as YAML. This is produced when PyYAML's `yaml.load` raises an error.
- `ali:toplevel-nondict`: The YAML header was not parsed as a dictionary. `key: value` pairs should be provided.
- `ali:schema`: The YAML header did not conform to its schema. See the error message for more details.
- `ali:key-order`: The `package`, `version` and `tag` keys were not found in the correct order.
  These keys should be the first in the file, in the above order (if present).
  Additionally, the `requires` key must come before `build_requires`.

## GitHub Actions integration

You can run `alidistlint` as part of a GitHub Action using `-f github`. In that case, `alidistlint` will annotate files with the errors found in them.

`alidistlint` will exit with a non-zero exit code if any errors were found, which will cause the Action to fail.

## Vim integration

Put the following in your `.vimrc`:

```vim
autocmd BufNewFile,BufRead *alidist/*.sh set makeprg=alidistlint\ -f\ gcc\ % errorformat=%f:%l:%c:\ %t%*[a-z]:\ %m
" If you want to automatically re-run the linter on every save:
autocmd BufWritePost *alidist/*.sh make
```

Then you can use `:make` to run the linter, `:cl` to see the error list, and navigate from one error to another using `:cp` (previous), `:cc` (current) and `:cn` (next).

## Emacs integration

Here is a simple Flycheck checker using `alidistlint`.
You can set this to check alidist recipes.

```elisp
(require 'flycheck)
(flycheck-def-executable-var alidist "alidistlint")
(flycheck-define-checker alidist
  "A syntax checker and linter for alidist recipes."
  ;; `flycheck-alidist-executable' automatically overrides the car of the
  ;; :command list if set and non-nil.
  :command ("alidistlint" "--format=gcc" source)
  :error-patterns
  ((error line-start (file-name) ":" line ":" column ": error: " (message)
          " [" (id (minimal-match (one-or-more not-newline))) "]" line-end)
   (warning line-start (file-name) ":" line ":" column ": warning: " (message)
            " [" (id (minimal-match (one-or-more not-newline))) "]" line-end)
   (info line-start (file-name) ":" line ":" column ": note: " (message)
         " [" (id (minimal-match (one-or-more not-newline))) "]" line-end)))
(add-to-list 'flycheck-checkers 'alidist)
```

[alidist]: https://github.com/alisw/alidist
[shellcheck]: https://www.shellcheck.net/
[yamllint]: https://yamllint.readthedocs.io/
