(charmcraft-analyzers-and-linters)= # Analysers and linters The following are the different checks that Charmcraft will run explicitly (when the user executes its `analyse` method) or implicitly (when packing charms). Any linter or analysis can be set in [the config](https://juju.is/docs/sdk/charmcraft-config) to be excluded from the normal execution. Also note that if any linter ends in error it will block the charm packing (you can pack it anyway using the `--force` option). You can read more about these checks in the [Charmcraft Analyze Specification](https://discourse.charmhub.io/t/proposal-charmcraft-analyze/4792). ## Language attribute If through analysis, the charm can be detected as being a Python based charm, then language shall be set to `python`. If not, it shall be set to `unknown`. When working with Python, it is possible to only publish byte-code. By doing so, troubleshooting is a harder task. Charms with Python sources delivered are preferred. This attribute meets the requirements to be set to `python` when: - the charm has a text dispatch which executes a .py - the charm has a .py entry point - the entry point file is executable ## Framework attribute When using `ops`, it is best to import it from a common path and not make customisation or package forks from it. If `ops` code is detected in the charm sources, this attribute's value shall be set to `operator`. If not, the charm may be using the Reactive Framework, and in this case the attribute value will be `reactive`. Else, it shall be set to `unknown`. This check hint meets the requirements for `ops` when: - language attribute is set to `python` - the charm contains `venv/ops` - the charm imports `ops` in the entry point The requirements for the Reactive Framework are: ...or the Reactive Framework is used, if the charm... - has a metadata.yaml with `name` in it - has a `reactive/.py` file that imports `charms.reactive` - has a file name that starts with `charms.reactive-` inside the `wheelhouse` directory ## Juju metadata linter This linter verifies that the `metadata.yaml` file exists and is sane. The charm is considered to have a valid metadata if the following checks are true: - the `metadata.yaml` is present - it is a valid YAML file - it has at least the following fields: `name`, `summary`, and `description` ## Juju actions linter *(new in 1.4)* This linter verifies that the `actions.yaml` file, if exists, is a valid YAML file. The file is optional. The file contents are not verified. ## Juju config linter *(new in 1.4)* This linter verifies that the `config.yaml` file, if exists, is valid. This file is optional. If the file exists, it is considered valid if the following checks are true: - it has the `options` key - it is a dictionary - each item inside has the mandatory `type` key Check how to [create config.yaml and configure charms](https://discourse.charmhub.io/t/creating-config-yaml-and-configuring-charms/1039) for more information. ## Charm entrypoint linter *(new in 2.1)* Check the entry point is correct. Note that even if most modern charms has a typical `src/charm.py` entry point, not all charms have one, as Juju has different ways to deliver its events. This linter validates that, if an entry point is called from the `dispatch` file, that entry point... - exists - is a file - is executable The entry point content is *not* validated.