Style Guide
80 character width
Only extend past 80 characters if long variable names make it impossible. Continue long lines with breaks. Prefer human readability.
- ansible.builtin.set_fact:
JWT_SIGNING_PRIVATE_KEY_FILE:
'{{ forgejo_config_server_app_data_path }}/jwt/private.pem',
JWT_SIGNING_ALGORITHM: '{{
forgejo_config_oauth2_jwt_signing_algorithm | upper
}}',
SSH_TRUSTED_USER_CA_KEYS_FILENAME: '{{
_forgejo_home ~ "/.ssh/ca_trust_chain_root.pem" ~
forgejo_config_server_ssh_trusted_user_ca_keys_filename
}}',
# A vertical space will automatically disable jinja[spacing] test.
- ansible.builtin.set_fact:
data_annotation: "{{ {} | r_pufky.data.v3(
section='system.properties',
key='unifi.https.sslEnabledProtocols',
raw=unifi_cfg_legacy_properties_unifi_https_ssl_enabled_protocols,
data=(
unifi_cfg_legacy_properties_unifi_https_ssl_enabled_protocols |
join(',')
),
default=['TLSv1', 'SSLv2Hello'],
hint='list of str',
keep=false,
order=17
) }}"
Accepted Lint Disables
Isolate disable impact. Never use global lint disables for a project.
---
# yamllint disable rule:line-length
some really wide block text
# yamllint enable rule:line-length
some_long_yaml_line: 0 # yamllint disable-line rule:line-length
# Provide context for NOQA disables immediately.
- name: 'Annotate | sanitize & annotate service defaults'
ansible.builtin.set_fact: # noqa jinja[spacing] readability.
_unifi_srv_legacy_enable: "{{ {} | r_pufky.data.v3(
raw=unifi_srv_legacy_enable,
..
) }}"
Name Directives
Tasks
Use bare descriptions with pipes for multi-part steps.
- name: 'Config'
ansible.builtin.include_tasks: 'config.yml' # tasks/main.yml
- name: 'File | disable firewall' # tasks/file.yml
when: not ufw_enable
community.general.ufw:
state: 'disabled'
- name: 'Sub section | file | disable firewall' # tasks/sub_section/file.yml.
when: not ufw_enable
community.general.ufw:
state: 'disabled'
Clause Order
Prioritized for readability and clarity.
- name: 'task with a clause'
when: some_var_to_test # place 'when' next to loop if clause uses loop item.
notify: 'handler'
community.general.ufw:
state: 'disabled'
become: true
register: _some_var
loop: '{{ user_accounts }}'
loop_control:
label: '{{ item.user }}'
Handler (listen clauses)
Use listen clause to run multiple handlers for a given task. listen can be a list, allowing for specific combinations as needed.
Execution order is always the order as written in handlers.yml,
regardless of call order.
Handlers.
- name: 'Handlers | ifreload'
listen:
- 'Handlers | reload restart networking'
- 'Handlers | reload restart FRR'
ansible.builtin.command: '/usr/sbin/ifreload -a'
become: true
changed_when: false
- name: 'Handlers | restart networking'
listen: 'Handlers | reload restart networking'
when: network_systemctl_network_restart
ansible.builtin.service:
name: 'networking'
state: 'restarted'
changed_when: true
- name: 'Handlers | restart FRR'
listen: 'Handlers | reload restart frr'
ansible.builtin.service:
name: 'frr'
state: 'restarted'
Usage.
- name: 'run restart networking'
notify: 'Handlers | reload restart networking'
...
- name: 'run ifreload, restart networking'
notify: 'Handlers | reload restart networking'
...
- name: 'run ifreload, restart FRR'
notify: 'Handlers | reload restart FRR'
...
File Documentation
Provide development notes, overall process, required state before executing, post-execution state, and related information for understanding what tasks are trying to accomplish.
A developer should be able to read this section and get an understanding of what you are trying to do without explicitly walking through each step (that's what tasks do!).
###############################################################################
# Capped Header (Context)
###############################################################################
# Immediate start description of task set.
#
# WARNING
# > Detailed end-user explanation of warning. **ALL** warnings are copied
# > verbatim to README.md.
#
# NOTE
# > Detailed explanation for developer of critical cases which hard to debug
# > failures will occur. Provide explanation, workarounds, and fixes.
#
# Requires role_other_option=true.
# ⋮Requires:
# ⋮* multi_option_one='value'.
# ⋮* multi_option_two=true.
#
# Versions (Schematic):
# MAJOR: Unsafe - requires major role changes; only default MAJOR version
# is supported. See other branches if they exist.
# MINOR: Unsafe - Paperless has a history of introducing breaking changes
# on minor updates (see 2.14, 2.15, 2.16). These should be
# considered 'major' versions. See other branches if they exist.
# PATCH: Safe - Usually requires no role updates. Some have included
# breaking changes (2.16.0 - 2.16.2).
# RECOMMEND: Only increment PATCH. Never use 'latest'.
# ⋮Always recommend and provide context for safe option changes.
#
# Security: CVE-2023-48795
# CVE:
# * https://nvd.nist.gov/vuln/detail/cve-2023-48795
# * https://nvd.nist.gov/vuln/detail/cve-2023-46445
# * https://nvd.nist.gov/vuln/detail/cve-2023-46446
# * https://nvd.nist.gov/vuln/detail/cve-2024-41909
# Decision: remove chacha20 cipher, *-etm MAC - disables attack for modern
# systems, remove when OpenSSH 9.6 released with strict key exchange.
# Mitigation:
# * remove 'chacha20-poly1305@openssh.com' from client ciphers.
# * remove '*-etm@openssh.com' from server macs.
# Reference:
# * https://terrapin-attack.com/#scanner
# * https://www.openssh.com/txt/release-9.6
# ⋮Most critical security vulnerability first.
#
# Decision: Only manage owner - REST API does not provide a good way to set
# user passwords (requires old and new passwords), etc; without directly
# editing DB. Instead create required user so user can login.
# ⋮Explain opinionated or complex decision for implementing a specific way.
# ⋮Be clear and concise as to decision and supporting reasoning.
#
# Paragraph documentation.
# ⋮Make it unambiguously clear what variable does. Present, active tense,
# ⋮removing superfluous words.
# ⋮
# ⋮If it took more than a few seconds to understand write it down now.
#
# Special Case:
# value: Description (Vertically align values, min indent 2 spaces).
# other_value: Other.
# ⋮Special Case:
# ⋮* Non value based cases.
# ⋮* All paths are prepended with some_var.
# ⋮* Wildcards allowed.
#
# Values:
# none: explicitly disable use of an authentication agent.
# '': no default system agent (default).
# ':': clarify colon usage or cases where colon could be confused.
# SSH_AUTH_SOCK: get socket location from SSH_AUTH_SOCK environment variable.
# $*: strings beginning with $ will be treated as environment
# variable containing the location of the socket.
# Values:
# {VALUE}: additional values for value element.
# ⋮All docstrings can be nested as needed for additional context.
# ⋮Always mark the default option with '(default)'.
#
# Args:
# db: Postgres DB to manage.
# ⋮Explicitly for block/loop idioms to define what variables are required for
# ⋮task execution.
#
# Generates:
# _paperless_ngx: dict - Role runtime specific config.
# _paperless_ngx_map: list of dict - Annotated config map.
# _paperless_ngx_order: list of str - Config section order.
# ⋮Runtime variables that may be consumed in other role task files.
#
# Exports:
# _sqlite_sql_results: dict - User consumable return values from execution.
# ⋮Exported variables end-users may consume. Must update README.md.
# ⋮
# ⋮README.md:
# ⋮ ### Generated Variables
# ⋮ After successful execution the following variables are available for
# ⋮ further manipulation during the same play (standard role variable scope):
# ⋮
# ⋮ Variable | type | Description
# ⋮ ---------------------|------|-----------------------------------------
# ⋮ _sqlite_sql_results | dict | registered return results from command.
#
# Reference:
# * https://manpages.debian.org/bookworm/openssh-client/ssh_config.5.en.html
- name: 'always use one vertical space before code'
Variable Documentation
Explicitly document variable use for end users. Only remove sections which are not relevant to variable use even if trivial. A user will not understand something you implicitly do.
# One line active description of variable.
# ⋮Single line: Description (unit). Default: {VALUE}.
# ⋮Boolean values must declare what bool does (enable/disable).
#
# WARNING
# > Detailed end-user explanation of warning. **ALL** warnings are copied
# > verbatim to README.md.
#
# NOTE
# > Detailed explanation for developer of critical cases which hard to debug
# > failures will occur. Provide explanation, workarounds, and fixes.
#
# Requires role_other_option=true.
# ⋮Requires:
# ⋮* multi_option_one='value'.
# ⋮* multi_option_two=true.
#
# Versions (Schematic):
# MAJOR: Unsafe - requires major role changes; only default MAJOR version
# is supported. See other branches if they exist.
# MINOR: Unsafe - Paperless has a history of introducing breaking changes
# on minor updates (see 2.14, 2.15, 2.16). These should be
# considered 'major' versions. See other branches if they exist.
# PATCH: Safe - Usually requires no role updates. Some have included
# breaking changes (2.16.0 - 2.16.2).
# RECOMMEND: Only increment PATCH. Never use 'latest'.
# ⋮Always recommend and provide context for safe option changes.
#
# Security: CVE-2023-48795
# CVE:
# * https://nvd.nist.gov/vuln/detail/cve-2023-48795
# * https://nvd.nist.gov/vuln/detail/cve-2023-46445
# * https://nvd.nist.gov/vuln/detail/cve-2023-46446
# * https://nvd.nist.gov/vuln/detail/cve-2024-41909
# Decision: remove chacha20 cipher, *-etm MAC - disables attack for modern
# systems, remove when OpenSSH 9.6 released with strict key exchange.
# Mitigation:
# * remove 'chacha20-poly1305@openssh.com' from client ciphers.
# * remove '*-etm@openssh.com' from server macs.
# Reference:
# * https://terrapin-attack.com/#scanner
# * https://www.openssh.com/txt/release-9.6
# ⋮Most critical security vulnerability first.
#
# Decision: Only manage owner - REST API does not provide a good way to set
# user passwords (requires old and new passwords), etc; without directly
# editing DB. Instead create required user so user can login.
# ⋮Explain opinionated or complex decision for implementing a specific way.
# ⋮Be clear and concise as to decision and supporting reasoning.
#
# Paragraph documentation.
# ⋮Make it unambiguously clear what variable does. Present, active tense,
# ⋮removing superfluous words.
# ⋮
# ⋮If it took more than a few seconds to understand write it down now.
#
# Special Case:
# value: Description (Vertically align values, min indent 2 spaces).
# other_value: Other.
# ⋮Special Case:
# ⋮* Non value based cases.
# ⋮* All paths are prepended with some_var.
# ⋮* Wildcards allowed.
#
# Values:
# none: explicitly disable use of an authentication agent.
# '': no default system agent (default).
# ':': clarify colon usage or cases where colon could be confused.
# SSH_AUTH_SOCK: get socket location from SSH_AUTH_SOCK environment variable.
# $*: strings beginning with $ will be treated as environment
# variable containing the location of the socket.
# Values:
# {VALUE}: additional values for value element.
# ⋮All docstrings can be nested as needed for additional context.
# ⋮Always mark the default option with '(default)'.
#
# role_multi_complex:
# list of dict - definitions for local configuration.
# - config: str - name of local config ({INCLUDE}/{CONFIG}).
# state: str - whether config should be managed or removed.
# Additional description details here.
#
# Reference:
# * https://example.com
# Values:
# present: manage configuration
# absent: remove configuration
# Default: 'present'.
# options: dict - ssh_config options to manage (per ssh_config options).
# file: str - file location.
# mode: str - octal file permissions.
# Default: '0644'.
# ⋮For complex variables using condensed docstring format. Nest as needed.
# ⋮Always provide examples showing actual test data (see below).
#
# role_multi_complex:
# - config: 'custom_ssh_config'
# state: 'present'
# options:
# file: '/etc/example'
# mode: '0644'
#
# role_multi_complex:
# - config: 'alternative_config'
# state: 'absent'
# - config: 'custom_ssh_config'
# state: 'present'
# options:
# file: '/etc/example'
# mode: '0644'
#
# Variable: variable_name | type
# ⋮Defines an inline extended variable for a variable defined in another file.
# ⋮**Only** used for extremely large and complex configurations that have
# ⋮multiple overlapping, duplicated options, resulting in 5k+ line default
# ⋮values files.
# ⋮
# ⋮Extended options are defined in a separate file (with no
# ⋮actual YAML variables) and cross-reference actual configuration location.
# ⋮See r_pufky.deb.systemd defaults for example.
#
# Default: [] (un-managed).
# ⋮ Default: (description).
# ⋮ - 'long'
# ⋮ - 'defaults'
#
# Reference:
# * https://manpages.debian.org/bookworm/openssh-client/ssh_config.5.en.html