Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 9 additions & 22 deletions docs/reuse/best-practices.txt
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
**[How to write and structure charm code](https://documentation.ubuntu.com/ops/latest/howto/write-and-structure-charm-code/)**
- Avoid using Charmcraft's `charm` plugin if possible. Instead, {external+charmcraft:ref}`migrate to the uv plugin <howto-migrate-to-uv>` or the {external+charmcraft:ref}`poetry plugin <howto-migrate-to-poetry>`. See [Add Python dependencies to pyproject.toml and update the lock file](#define-the-required-dependencies).
- Ensure that the `pyproject.toml` *and* the lock file are committed to version control, so that exact versions of charms can be reproduced. See [Add Python dependencies to pyproject.toml and update the lock file](#define-the-required-dependencies).
- Ensure that tooling is configured to automatically detect new versions, particularly security releases, for all your dependencies. See [Add Python dependencies to pyproject.toml and update the lock file](#define-the-required-dependencies).
- Name the repository using the pattern ``<charm name>-operator`` for a single charm, or ``<base charm name>-operators`` when the repository will hold multiple related charms. For the charm name, see {external+charmcraft:ref}`Charmcraft | Specify a name <specify-a-name>`. See [Create a repository and initialise it](#create-a-repository-and-initialise-it).
- Set the [`requires-python`](https://packaging.python.org/en/latest/specifications/pyproject-toml/#requires-python) version in your `pyproject.toml` so that tooling will detect any use of Python features not available in the versions you support. See [Use the Python provided by the base](#define-the-required-dependencies).
- Ensure that tooling is configured to automatically detect new versions, particularly security releases, for all your dependencies. See [Add Python dependencies to pyproject.toml and generate a lock file](#define-the-required-dependencies).
- Ensure that the `pyproject.toml` *and* the lock file are committed to version control, so that exact versions of charms can be reproduced. See [Add Python dependencies to pyproject.toml and generate a lock file](#define-the-required-dependencies).
- The quality assurance pipeline of a charm should be automated using a continuous integration (CI) system. See [Validate your charm with every change](#validate-your-charm-with-every-change).

**[How to log from your charm](https://documentation.ubuntu.com/ops/latest/howto/log-from-your-charm/)**
- Capture output to `stdout` and `stderr` in your charm and use the logging and warning functionality to send messages to the charm user, rather than rely on Juju capturing output. In particular, you should avoid `print()` calls, and ensure that any subprocess calls capture output.
- Ensure that log messages are clear, meaningful, and provide enough information for the user to troubleshoot any issues. Avoid spurious logging. For instance, try not to log when event handlers are called, as the Juju controller does this automatically.
- Never log credentials or other sensitive information.
**[Manage libraries](https://documentation.ubuntu.com/ops/latest/howto/manage-libraries/)**
- Libraries should never mutate the status of a unit or application. Instead, use return values, or raise exceptions and let them bubble back up to the charm for the charm author to handle as they see fit. See [Write a library](#manage-libraries-write-a-library).

**[How to manage charms](https://documentation.ubuntu.com/ops/latest/howto/manage-charms/)**
- All charms should provide the commands configured by the Charmcraft profile, to allow easy testing across the charm ecosystem. It's fine to tweak the configuration of individual tools, or to add additional commands, but keep the command names and meanings that the profile provides. See [Develop your charm](#develop-your-charm).

**[Manage libraries](https://documentation.ubuntu.com/ops/latest/howto/manage-libraries/)**
- Libraries should never mutate the status of a unit or application. Instead, use return values, or raise exceptions and let them bubble back up to the charm for the charm author to handle as they see fit. See [Write a library](#manage-libraries-write-a-library).
**[How to log from your charm](https://documentation.ubuntu.com/ops/latest/howto/log-from-your-charm/)**
- Capture output to `stdout` and `stderr` in your charm and use the logging and warning functionality to send messages to the charm user, rather than rely on Juju capturing output. In particular, you should avoid `print()` calls, and ensure that any subprocess calls capture output.
- Ensure that log messages are clear, meaningful, and provide enough information for the user to troubleshoot any issues. Avoid spurious logging. For instance, try not to log when event handlers are called, as the Juju controller does this automatically.
- Never log credentials or other sensitive information.

**[Manage configuration](https://documentation.ubuntu.com/ops/latest/howto/manage-configuration/)**
- Don't duplicate model-level configuration options that are controlled by {external+juju:ref}`juju model-config <command-juju-model-config>`. See [Define a configuration option](#define-a-configuration-option).

**[Manage charms](https://documentation.ubuntu.com/charmcraft/latest/howto/manage-charms/)**
- If you're setting up a ``git`` repository: name it using the pattern ``<charm name>-operator``. For the charm name, see {external+charmcraft:ref}`specify-a-name`. See {external+charmcraft:ref}`Initialise a charm <initialise-a-charm>`.

**[Manage resources](https://documentation.ubuntu.com/charmcraft/latest/howto/manage-resources/)**
- For resources that are binary files, provide binaries for all the CPU architectures you intend to support. See {external+charmcraft:ref}`Publish a resource on Charmhub <publish-a-resource>`.

**[``charmcraft.yaml`` file](https://documentation.ubuntu.com/charmcraft/latest/reference/files/charmcraft-yaml-file/)**
- Prefer lowercase alphanumeric action names, and use hyphens (-) to separate words. For charms that have already standardised on underscores, it is not necessary to change them, and it is better to be consistent within a charm then to have some action names be dashed and some be underscored. See {external+charmcraft:ref}`actions <charmcraft-yaml-key-actions>`.
- Just like Juju, a charm is an opinionated tool. Configure the application with the best defaults (ideally the application is deployable without providing any configuration at deploy time), and only expose application configuration options when necessary. See {external+charmcraft:ref}`config <charmcraft-yaml-key-config>`.
- Prefer lowercase alphanumeric option names, separated with dashes if required. For charms that have already standardised on underscores, it is not necessary to change them, and it is better to be consistent within a charm then to have some config names be dashed and some be underscored. See {external+charmcraft:ref}`config <charmcraft-yaml-key-config>`.
- For very complex applications, consider providing configuration profiles, which can group values for large configs together. For example, a ``profile: large`` that tweaks multiple options under the hood to optimize for larger deployments, or a ``profile: ci`` for limited resource usage during testing. See {external+charmcraft:ref}`config <charmcraft-yaml-key-config>`.
- Documentation links should apply to the charm, and not to the application that is being charmed. Assume that the user already has basic competency in the use of the application. See {external+charmcraft:ref}`links <charmcraft-yaml-key-documentation>`.
- The charm name should be slug-oriented (ASCII lowercase letters, numbers, and hyphens) and follow the pattern ``<workload name in full>[<function>][-k8s]``. For example, ``argo-server-k8s``. Include the ``-k8s`` suffix on all charms that run on a Kubernetes cloud, unless the charm has no workload or you know that there will never be a machine version of the charm. Don't include an organization or publisher in the name. Don't add an ``operator`` or ``charm`` prefix or suffix. For naming a repository, see {external+charmcraft:ref}`initialise-a-charm`. See {external+charmcraft:ref}`name <charmcraft-yaml-key-name>`.
- Include the ``optional`` key in all endpoint definitions, rather than relying on the default value to indicate that the relation is required. Although this field is not enforced by Juju, including it makes it clear to users (and other tools) whether the relation is required. See {external+charmcraft:ref}`<endpoint role> <charmcraft-yaml-key-requires>`.