Organize workspace policies by task
This commit is contained in:
12
AGENTS.md
12
AGENTS.md
@@ -12,9 +12,13 @@ is an independent Git repository.
|
|||||||
- Read [the workspace orientation](docs/orientation.md) before selecting,
|
- Read [the workspace orientation](docs/orientation.md) before selecting,
|
||||||
inspecting, or modifying a repository. It maps the repositories and defines
|
inspecting, or modifying a repository. It maps the repositories and defines
|
||||||
the canonical sources of truth.
|
the canonical sources of truth.
|
||||||
- Read [the workspace conventions](docs/conventions.md) before reviewing or
|
- Read [the workspace conventions](docs/conventions.md) before making any
|
||||||
changing Ansible, preparing a feature roadmap or implementation plan, or
|
repository change. They define the workspace-wide rules and route work to
|
||||||
making any repository change. It defines the normative house style and
|
specialized policy.
|
||||||
working conventions.
|
- Read [the Ansible house style](docs/ansible.md) before designing,
|
||||||
|
implementing, or reviewing Ansible roles or collections, including plans
|
||||||
|
that specify such work.
|
||||||
|
- Read [the testing house style](docs/testing.md) before creating, changing,
|
||||||
|
reviewing, or auditing tests, including plans that specify test work.
|
||||||
- Read [the planning policy](docs/planning.md) before preparing a feature
|
- Read [the planning policy](docs/planning.md) before preparing a feature
|
||||||
roadmap or implementation plan or managing an ongoing work stream.
|
roadmap or implementation plan or managing an ongoing work stream.
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ only workspace documentation, planning, and shared development utilities.
|
|||||||
|
|
||||||
## Start Here
|
## Start Here
|
||||||
|
|
||||||
- [`AGENTS.md`](AGENTS.md) describes repository boundaries and working
|
- [`AGENTS.md`](AGENTS.md) describes repository boundaries and routes each
|
||||||
conventions.
|
kind of work to its required policy documents.
|
||||||
- [`workspace.yml`](workspace.yml) inventories the repositories used during
|
- [`workspace.yml`](workspace.yml) inventories the repositories used during
|
||||||
development.
|
development.
|
||||||
- [`docs/roadmap/mvp.md`](docs/roadmap/mvp.md) records settled MVP decisions
|
- [`docs/roadmap/mvp.md`](docs/roadmap/mvp.md) records settled MVP decisions
|
||||||
|
|||||||
97
docs/ansible.md
Normal file
97
docs/ansible.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# Ansible House Style
|
||||||
|
|
||||||
|
This policy is normative for designing, implementing, and reviewing Ansible
|
||||||
|
roles and collections in this workspace.
|
||||||
|
|
||||||
|
## Role Implementation
|
||||||
|
|
||||||
|
- Always use the smallest clear sequence of declarative tasks that reaches the
|
||||||
|
required end state.
|
||||||
|
- Prefer `ansible.builtin` modules where they directly fit the task.
|
||||||
|
`community.general` is an approved, stable dependency and its modules may be
|
||||||
|
selected freely when appropriate; declare and pin the collection wherever a
|
||||||
|
role or collection depends on it.
|
||||||
|
- Do not strengthen the specification. Implement the requested invariants
|
||||||
|
without inventing additional guarantees for integrity, provenance, drift
|
||||||
|
recovery, corruption detection, rollback, or similar behavior.
|
||||||
|
- Prefer convergence over state inspection. Declare what should be true and
|
||||||
|
let the relevant module reconcile it.
|
||||||
|
- Trust Ansible's abstraction boundary. A module that manages state owns the
|
||||||
|
checks necessary to manage that state. Inspect it beforehand only when the
|
||||||
|
observed state is independently required.
|
||||||
|
- State inspection is justified when its result is necessary to decide whether
|
||||||
|
an imperative operation must run, such as checking whether an arbitrary
|
||||||
|
build command's output exists.
|
||||||
|
- Production role tasks establish required application state; they do not test
|
||||||
|
the role's own implementation. Put implementation verification in
|
||||||
|
repository-local tests unless the specification explicitly requires runtime
|
||||||
|
validation during convergence.
|
||||||
|
- For an unavoidable `command` or `shell` task, declare the operation's change
|
||||||
|
semantics as required by ansible-lint. A conditionally executed mutation may
|
||||||
|
use `changed_when: true`; a read-only command should use
|
||||||
|
`changed_when: false`. This describes an imperative operation and does not
|
||||||
|
replace the idempotence of a state-management module.
|
||||||
|
- Apply `become: true` to individual tasks that require elevated privileges.
|
||||||
|
Do not require callers to escalate an entire play merely to use a role.
|
||||||
|
- Complexity requires a requirement. Every additional task, conditional,
|
||||||
|
registered variable, or state probe must correspond to behavior the role is
|
||||||
|
required to provide.
|
||||||
|
- Persisted role-private state is a design smell. Fingerprints, checksum
|
||||||
|
databases, stamps, manifests, and similar bookkeeping require specific
|
||||||
|
justification.
|
||||||
|
- **Assume convergence first.** Before adding machinery for an edge case,
|
||||||
|
determine whether rerunning the ordinary desired-state operations already
|
||||||
|
repairs it.
|
||||||
|
- Consider whether a conditional task or a notified handler best expresses the
|
||||||
|
dependency. A `when` condition keeps triggers visible at the action site but
|
||||||
|
grows with their number. Notifications keep the action independent of the
|
||||||
|
number of notifiers, but distribute the control flow and defer execution
|
||||||
|
until the next handler flush. An explicit
|
||||||
|
`ansible.builtin.meta: flush_handlers` affects all pending handlers in the
|
||||||
|
play.
|
||||||
|
- Treat `rakestraw-ansible` as a style reference for direct tasks, shallow
|
||||||
|
control flow, and concise variable use, while retaining current practices
|
||||||
|
such as fully qualified collection names.
|
||||||
|
|
||||||
|
## Application Configuration Interfaces
|
||||||
|
|
||||||
|
- Expose application configuration through documented, field-specific role
|
||||||
|
variables suitable for `host_vars`, `group_vars`, play variables, and
|
||||||
|
composing roles.
|
||||||
|
- Give structurally required fields concrete defaults. Define optional
|
||||||
|
application settings as `null` unless the role intentionally owns the
|
||||||
|
corresponding policy.
|
||||||
|
- Treat a null optional variable as "omit this field from the rendered
|
||||||
|
configuration." Do not copy documented upstream defaults into role defaults
|
||||||
|
merely to write them back to the application.
|
||||||
|
- Let the application supply its built-in defaults for omitted fields. This
|
||||||
|
avoids freezing a duplicate defaults database in Ansible and permits upstream
|
||||||
|
default changes to take effect naturally.
|
||||||
|
- Use `is not none` when conditionally rendering optional values. Do not use
|
||||||
|
truthiness, because false, zero, an empty string, or an empty collection may
|
||||||
|
be an intentional value.
|
||||||
|
- Emit a nested configuration section only when at least one of its descendant
|
||||||
|
variables is non-null.
|
||||||
|
- Serialize strings and collections with appropriate Ansible or Jinja filters.
|
||||||
|
Do not construct YAML quoting manually.
|
||||||
|
- Keep argument specifications aligned with the public variables. Optional
|
||||||
|
nullable variables are not required; use a permissive type only when the
|
||||||
|
native application accepts more than one scalar type.
|
||||||
|
- Prefer one field-specific interface. Do not provide a parallel raw mapping,
|
||||||
|
template override, or merge mechanism unless a concrete requirement defines
|
||||||
|
its precedence and behavior.
|
||||||
|
- Application roles expose native configuration choices. The suite-level role
|
||||||
|
supplies cross-application and deployment-specific policy through those
|
||||||
|
variables.
|
||||||
|
- Manage the resulting file with one ordinary `ansible.builtin.template` task.
|
||||||
|
Do not add configuration assembly facts, preliminary file inspection, or
|
||||||
|
production validation unless independently required.
|
||||||
|
- Configuration tests should use explicitly supplied representative values to
|
||||||
|
exercise conditional rendering, null omission, intentional falsey values,
|
||||||
|
native configuration validity, and caller-facing composition boundaries.
|
||||||
|
They should follow [the testing house style](testing.md) rather than
|
||||||
|
snapshotting the current default document.
|
||||||
|
|
||||||
|
Role defaults define what Ansible intends to manage, not a mirror of every
|
||||||
|
application default. A concrete default means the role deliberately owns that
|
||||||
|
policy; a null default leaves the policy with the application.
|
||||||
@@ -1,6 +1,17 @@
|
|||||||
# Workspace Conventions
|
# Workspace Conventions
|
||||||
|
|
||||||
## Working Conventions
|
These conventions apply to all work in this workspace. Read the specialized
|
||||||
|
policy for the work being performed as well:
|
||||||
|
|
||||||
|
- Read [the Ansible house style](ansible.md) before designing, implementing,
|
||||||
|
or reviewing Ansible roles or collections, including their configuration
|
||||||
|
interfaces.
|
||||||
|
- Read [the testing house style](testing.md) before creating, changing,
|
||||||
|
reviewing, or auditing tests.
|
||||||
|
- Read [the planning policy](planning.md) before preparing or managing a
|
||||||
|
feature roadmap, implementation plan, or active work stream.
|
||||||
|
|
||||||
|
## Workspace-Wide Conventions
|
||||||
|
|
||||||
- Confirm the target repository before editing; never treat this directory as
|
- Confirm the target repository before editing; never treat this directory as
|
||||||
a monorepo.
|
a monorepo.
|
||||||
@@ -20,141 +31,3 @@
|
|||||||
run.
|
run.
|
||||||
- Do not duplicate an application contract in workspace documentation when a
|
- Do not duplicate an application contract in workspace documentation when a
|
||||||
link and a concise deployment consequence are sufficient.
|
link and a concise deployment consequence are sufficient.
|
||||||
|
|
||||||
## Ansible House Style (Normative)
|
|
||||||
|
|
||||||
- Always use the smallest clear sequence of declarative tasks that reaches the
|
|
||||||
required end state.
|
|
||||||
- Prefer `ansible.builtin` modules where they directly fit the task.
|
|
||||||
`community.general` is an approved, stable dependency and its modules may be
|
|
||||||
selected freely when appropriate; declare and pin the collection wherever a
|
|
||||||
role or collection depends on it.
|
|
||||||
- Do not strengthen the specification. Implement the requested invariants
|
|
||||||
without inventing additional guarantees for integrity, provenance, drift
|
|
||||||
recovery, corruption detection, rollback, or similar behavior.
|
|
||||||
- Prefer convergence over state inspection. Declare what should be true and
|
|
||||||
let the relevant module reconcile it.
|
|
||||||
- Trust Ansible's abstraction boundary. A module that manages state owns the
|
|
||||||
checks necessary to manage that state. Inspect it beforehand only when the
|
|
||||||
observed state is independently required.
|
|
||||||
- State inspection is justified when its result is necessary to decide whether
|
|
||||||
an imperative operation must run, such as checking whether an arbitrary
|
|
||||||
build command's output exists.
|
|
||||||
- Production role tasks establish required application state; they do not test
|
|
||||||
the role's own implementation. Put implementation verification in
|
|
||||||
repository-local tests unless the specification explicitly requires runtime
|
|
||||||
validation during convergence.
|
|
||||||
- For an unavoidable `command` or `shell` task, declare the operation's change
|
|
||||||
semantics as required by ansible-lint. A conditionally executed mutation may
|
|
||||||
use `changed_when: true`; a read-only command should use
|
|
||||||
`changed_when: false`. This describes an imperative operation and does not
|
|
||||||
replace the idempotence of a state-management module.
|
|
||||||
- Apply `become: true` to individual tasks that require elevated privileges.
|
|
||||||
Do not require callers to escalate an entire play merely to use a role.
|
|
||||||
- Complexity requires a requirement. Every additional task, conditional,
|
|
||||||
registered variable, or state probe must correspond to behavior the role is
|
|
||||||
required to provide.
|
|
||||||
- Persisted role-private state is a design smell. Fingerprints, checksum
|
|
||||||
databases, stamps, manifests, and similar bookkeeping require specific
|
|
||||||
justification.
|
|
||||||
- **Assume convergence first.** Before adding machinery for an edge case,
|
|
||||||
determine whether rerunning the ordinary desired-state operations already
|
|
||||||
repairs it.
|
|
||||||
- Consider whether a conditional task or a notified handler best expresses the
|
|
||||||
dependency. A `when` condition keeps triggers visible at the action site but
|
|
||||||
grows with their number. Notifications keep the action independent of the
|
|
||||||
number of notifiers, but distribute the control flow and defer execution
|
|
||||||
until the next handler flush. An explicit
|
|
||||||
`ansible.builtin.meta: flush_handlers` affects all pending handlers in the
|
|
||||||
play.
|
|
||||||
- Treat `rakestraw-ansible` as a style reference for direct tasks, shallow
|
|
||||||
control flow, and concise variable use, while retaining current practices
|
|
||||||
such as fully qualified collection names.
|
|
||||||
|
|
||||||
## Testing House Style (Normative)
|
|
||||||
|
|
||||||
- Use a classical state-based approach, also commonly described as Chicago or
|
|
||||||
Detroit style. Exercise the real role through its public interface and
|
|
||||||
observe the resulting deployed system.
|
|
||||||
- Test behavior owned by the role, not the current arrangement of tasks that
|
|
||||||
implements it. A useful test should normally remain valid after an internal
|
|
||||||
refactor that preserves the same public behavior.
|
|
||||||
- Require an immediate second role application to report no changes. Clean
|
|
||||||
repeated convergence is a first-class role outcome, not a test of any one
|
|
||||||
module.
|
|
||||||
- Distinguish configurable behavior from current defaults. To prove version
|
|
||||||
selection, explicitly request a version and verify that the application
|
|
||||||
reports that version. Do not assert that the same version remains the role's
|
|
||||||
default. For example, a useful test sets `audita_version: v0.9.0` and verifies
|
|
||||||
that the installed Audita reports `v0.9.0`; a harmful test asserts that
|
|
||||||
`v0.9.0` is the role's current default. The former continues to prove version
|
|
||||||
selection after the default advances to `v0.10.0`, while the latter fails
|
|
||||||
merely because of the intended update.
|
|
||||||
- Use a default invocation as a smoke test when useful, but do not snapshot
|
|
||||||
exact default values, selected commits, complete default configuration
|
|
||||||
documents, or counts of default variables. Those assertions are change
|
|
||||||
detectors that turn intentional updates into unrelated test failures.
|
|
||||||
- Do not assert task names, task order, individual `changed` or `skipped`
|
|
||||||
results, or other implementation traces. Inspect the final system and the
|
|
||||||
overall clean-repeat result instead.
|
|
||||||
- Do not test documented behavior of `ansible.builtin`, widely used
|
|
||||||
`community.general`, or other trusted modules. In particular, do not
|
|
||||||
independently verify file existence, ownership, permissions, package state,
|
|
||||||
checkout state, or template deployment merely to repeat module arguments.
|
|
||||||
- Test role-authored decisions only when they express meaningful public
|
|
||||||
behavior. Examples include an explicitly selected application version, a
|
|
||||||
caller-supplied build executable, configuration rendering with representative
|
|
||||||
non-null and falsey values, and composition of caller-supplied mappings.
|
|
||||||
- Verify application outcomes with the application's native interface when
|
|
||||||
practical. Prefer executing the installed application or its configuration
|
|
||||||
validator over reconstructing its rules in Ansible assertions.
|
|
||||||
- Self-evident declarative guards, including straightforward platform
|
|
||||||
assertions, do not require a negative test matrix.
|
|
||||||
- Prefer one representative case for a behavior over exhaustive combinations.
|
|
||||||
Every additional test must protect a requirement or a plausible regression,
|
|
||||||
not merely increase coverage.
|
|
||||||
- Keep syntax checking and linting as static validation. They complement the
|
|
||||||
behavioral suite but do not justify tests that freeze implementation details.
|
|
||||||
|
|
||||||
## Application Configuration Interfaces
|
|
||||||
|
|
||||||
- Expose application configuration through documented, field-specific role
|
|
||||||
variables suitable for `host_vars`, `group_vars`, play variables, and
|
|
||||||
composing roles.
|
|
||||||
- Give structurally required fields concrete defaults. Define optional
|
|
||||||
application settings as `null` unless the role intentionally owns the
|
|
||||||
corresponding policy.
|
|
||||||
- Treat a null optional variable as "omit this field from the rendered
|
|
||||||
configuration." Do not copy documented upstream defaults into role defaults
|
|
||||||
merely to write them back to the application.
|
|
||||||
- Let the application supply its built-in defaults for omitted fields. This
|
|
||||||
avoids freezing a duplicate defaults database in Ansible and permits upstream
|
|
||||||
default changes to take effect naturally.
|
|
||||||
- Use `is not none` when conditionally rendering optional values. Do not use
|
|
||||||
truthiness, because false, zero, an empty string, or an empty collection may
|
|
||||||
be an intentional value.
|
|
||||||
- Emit a nested configuration section only when at least one of its descendant
|
|
||||||
variables is non-null.
|
|
||||||
- Serialize strings and collections with appropriate Ansible or Jinja filters.
|
|
||||||
Do not construct YAML quoting manually.
|
|
||||||
- Keep argument specifications aligned with the public variables. Optional
|
|
||||||
nullable variables are not required; use a permissive type only when the
|
|
||||||
native application accepts more than one scalar type.
|
|
||||||
- Prefer one field-specific interface. Do not provide a parallel raw mapping,
|
|
||||||
template override, or merge mechanism unless a concrete requirement defines
|
|
||||||
its precedence and behavior.
|
|
||||||
- Application roles expose native configuration choices. The suite-level role
|
|
||||||
supplies cross-application and deployment-specific policy through those
|
|
||||||
variables.
|
|
||||||
- Manage the resulting file with one ordinary `ansible.builtin.template` task.
|
|
||||||
Do not add configuration assembly facts, preliminary file inspection, or
|
|
||||||
production validation unless independently required.
|
|
||||||
- Configuration tests should use explicitly supplied representative values to
|
|
||||||
exercise conditional rendering, null omission, intentional falsey values,
|
|
||||||
native configuration validity, and caller-facing composition boundaries.
|
|
||||||
They should follow the testing house style above rather than snapshotting the
|
|
||||||
current default document.
|
|
||||||
|
|
||||||
Role defaults define what Ansible intends to manage, not a mirror of every
|
|
||||||
application default. A concrete default means the role deliberately owns that
|
|
||||||
policy; a null default leaves the policy with the application.
|
|
||||||
|
|||||||
@@ -25,8 +25,11 @@ machine-readable inventory of paths and remotes.
|
|||||||
|
|
||||||
## Sources of Truth
|
## Sources of Truth
|
||||||
|
|
||||||
- [Workspace conventions](conventions.md): normative working and Ansible house
|
- [Workspace conventions](conventions.md): normative workspace-wide rules and
|
||||||
style.
|
policy routing.
|
||||||
|
- [Ansible house style](ansible.md): normative role, collection, and
|
||||||
|
application-configuration practices.
|
||||||
|
- [Testing house style](testing.md): normative behavioral-testing practices.
|
||||||
- [Planning policy](planning.md): normative feature planning and progress
|
- [Planning policy](planning.md): normative feature planning and progress
|
||||||
workflow.
|
workflow.
|
||||||
- [MVP roadmap](roadmap/mvp.md): settled MVP scope, architecture, and open
|
- [MVP roadmap](roadmap/mvp.md): settled MVP scope, architecture, and open
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
# Planning and Progress
|
# Planning and Progress
|
||||||
|
|
||||||
- Read and follow [the workspace conventions](conventions.md) before preparing
|
- Read and follow [the workspace conventions](conventions.md) before preparing
|
||||||
or revising any roadmap or implementation plan.
|
or revising any roadmap or implementation plan. Also read the specialized
|
||||||
|
policy applicable to the planned work: [the Ansible house style](ansible.md),
|
||||||
|
[the testing house style](testing.md), or both.
|
||||||
- Update [the MVP roadmap](roadmap/mvp.md) when a design question becomes a
|
- Update [the MVP roadmap](roadmap/mvp.md) when a design question becomes a
|
||||||
settled scope or architecture decision.
|
settled scope or architecture decision.
|
||||||
- Discuss and select the next unit of work before planning implementation.
|
- Discuss and select the next unit of work before planning implementation.
|
||||||
@@ -28,7 +30,9 @@
|
|||||||
GPT-5.6-Terra to execute sequentially. Number stages with consecutive
|
GPT-5.6-Terra to execute sequentially. Number stages with consecutive
|
||||||
integers beginning with `Stage 1`; do not skip numbers or use nested stage
|
integers beginning with `Stage 1`; do not skip numbers or use nested stage
|
||||||
numbering. Each stage must identify its repository, preconditions, required
|
numbering. Each stage must identify its repository, preconditions, required
|
||||||
behavior, validation, completion criteria, and expected commit.
|
policy reading, behavior, validation, completion criteria, and expected
|
||||||
|
commit. Direct the implementing agent to reread the applicable policy
|
||||||
|
documents immediately before beginning each stage.
|
||||||
- Resolve architectural choices during roadmap and plan review. Do not leave
|
- Resolve architectural choices during roadmap and plan review. Do not leave
|
||||||
unresolved design judgment to the implementation agent.
|
unresolved design judgment to the implementation agent.
|
||||||
- Update [workspace status](status.md) when cross-repository work starts,
|
- Update [workspace status](status.md) when cross-repository work starts,
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ for scope, rationale, target end state, and acceptance criteria.
|
|||||||
zero-based, decimal, nested, or nonsequential stage identifiers.
|
zero-based, decimal, nested, or nonsequential stage identifiers.
|
||||||
- Before each stage, confirm its preconditions and the working-tree state of
|
- Before each stage, confirm its preconditions and the working-tree state of
|
||||||
its owning repository.
|
its owning repository.
|
||||||
|
- Before each stage, read every document listed in that stage's Required Policy
|
||||||
|
Review. Do not rely on policy recalled from an earlier stage.
|
||||||
- Preserve unrelated and pre-existing changes.
|
- Preserve unrelated and pre-existing changes.
|
||||||
- Do not make unresolved product or architecture decisions during execution;
|
- Do not make unresolved product or architecture decisions during execution;
|
||||||
stop and report the decision required.
|
stop and report the decision required.
|
||||||
@@ -52,6 +54,21 @@ for scope, rationale, target end state, and acceptance criteria.
|
|||||||
|
|
||||||
State the single outcome delivered by this stage.
|
State the single outcome delivered by this stage.
|
||||||
|
|
||||||
|
### Required Policy Review
|
||||||
|
|
||||||
|
Before beginning this stage, read:
|
||||||
|
|
||||||
|
- `AGENTS.md`
|
||||||
|
- `docs/orientation.md`
|
||||||
|
- `docs/conventions.md`
|
||||||
|
- `<docs/ansible.md, docs/testing.md, and/or docs/planning.md as applicable>`
|
||||||
|
|
||||||
|
Replace the placeholder with every specialized policy applicable to this
|
||||||
|
stage. Include `docs/ansible.md` for Ansible design or implementation,
|
||||||
|
`docs/testing.md` for test work, and `docs/planning.md` for workspace planning
|
||||||
|
or progress management. Do not list an inapplicable policy merely for
|
||||||
|
completeness.
|
||||||
|
|
||||||
### Preconditions
|
### Preconditions
|
||||||
|
|
||||||
- List facts that must be true before editing begins.
|
- List facts that must be true before editing begins.
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ The directive remains in place. Unlike a desired-state module, the imperative
|
|||||||
build command must explicitly declare its change semantics for lint. The
|
build command must explicitly declare its change semantics for lint. The
|
||||||
existing `when` expression still determines whether the command runs, and
|
existing `when` expression still determines whether the command runs, and
|
||||||
`changed_when: true` accurately reports that every executed build changes the
|
`changed_when: true` accurately reports that every executed build changes the
|
||||||
binary. The distinction is now documented in `docs/conventions.md`.
|
binary. The distinction is now documented in `docs/ansible.md`.
|
||||||
|
|
||||||
## Finding 3: Make the Dependency-Opt-Out Test Prove the Selected Go Binary
|
## Finding 3: Make the Dependency-Opt-Out Test Prove the Selected Go Binary
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ three completed standalone-role test suites.
|
|||||||
|
|
||||||
## Governing Standard
|
## Governing Standard
|
||||||
|
|
||||||
Apply the normative testing house style in `docs/conventions.md`. In
|
Apply the normative testing house style in `docs/testing.md`. In
|
||||||
particular, the audit will favor tests that exercise the role through its
|
particular, the audit will favor tests that exercise the role through its
|
||||||
public variables and inspect meaningful final application behavior. It will
|
public variables and inspect meaningful final application behavior. It will
|
||||||
disfavor tests that:
|
disfavor tests that:
|
||||||
|
|||||||
47
docs/testing.md
Normal file
47
docs/testing.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Testing House Style
|
||||||
|
|
||||||
|
This policy is normative for creating, changing, reviewing, and auditing tests
|
||||||
|
in this workspace.
|
||||||
|
|
||||||
|
- Use a classical state-based approach, also commonly described as Chicago or
|
||||||
|
Detroit style. Exercise the real role through its public interface and
|
||||||
|
observe the resulting deployed system.
|
||||||
|
- Test behavior owned by the role, not the current arrangement of tasks that
|
||||||
|
implements it. A useful test should normally remain valid after an internal
|
||||||
|
refactor that preserves the same public behavior.
|
||||||
|
- Require an immediate second role application to report no changes. Clean
|
||||||
|
repeated convergence is a first-class role outcome, not a test of any one
|
||||||
|
module.
|
||||||
|
- Distinguish configurable behavior from current defaults. To prove version
|
||||||
|
selection, explicitly request a version and verify that the application
|
||||||
|
reports that version. Do not assert that the same version remains the role's
|
||||||
|
default. For example, a useful test sets `audita_version: v0.9.0` and verifies
|
||||||
|
that the installed Audita reports `v0.9.0`; a harmful test asserts that
|
||||||
|
`v0.9.0` is the role's current default. The former continues to prove version
|
||||||
|
selection after the default advances to `v0.10.0`, while the latter fails
|
||||||
|
merely because of the intended update.
|
||||||
|
- Use a default invocation as a smoke test when useful, but do not snapshot
|
||||||
|
exact default values, selected commits, complete default configuration
|
||||||
|
documents, or counts of default variables. Those assertions are change
|
||||||
|
detectors that turn intentional updates into unrelated test failures.
|
||||||
|
- Do not assert task names, task order, individual `changed` or `skipped`
|
||||||
|
results, or other implementation traces. Inspect the final system and the
|
||||||
|
overall clean-repeat result instead.
|
||||||
|
- Do not test documented behavior of `ansible.builtin`, widely used
|
||||||
|
`community.general`, or other trusted modules. In particular, do not
|
||||||
|
independently verify file existence, ownership, permissions, package state,
|
||||||
|
checkout state, or template deployment merely to repeat module arguments.
|
||||||
|
- Test role-authored decisions only when they express meaningful public
|
||||||
|
behavior. Examples include an explicitly selected application version, a
|
||||||
|
caller-supplied build executable, configuration rendering with representative
|
||||||
|
non-null and falsey values, and composition of caller-supplied mappings.
|
||||||
|
- Verify application outcomes with the application's native interface when
|
||||||
|
practical. Prefer executing the installed application or its configuration
|
||||||
|
validator over reconstructing its rules in Ansible assertions.
|
||||||
|
- Self-evident declarative guards, including straightforward platform
|
||||||
|
assertions, do not require a negative test matrix.
|
||||||
|
- Prefer one representative case for a behavior over exhaustive combinations.
|
||||||
|
Every additional test must protect a requirement or a plausible regression,
|
||||||
|
not merely increase coverage.
|
||||||
|
- Keep syntax checking and linting as static validation. They complement the
|
||||||
|
behavioral suite but do not justify tests that freeze implementation details.
|
||||||
Reference in New Issue
Block a user