Overview
Diffusion is the CLI tool for testing Ansible roles with Molecule. It manages the full testing lifecycle — converge, verify, lint, idempotence — inside a single Docker container, with built-in registry auth, HashiCorp Vault integration, and dependency locking.
Role Management
Initialize and configure Ansible roles interactively. Add dependencies, collections, and scenarios with a single command.
Docker-Based Testing
Full Molecule lifecycle — converge, verify, lint, idempotence — managed inside a single container. No manual setup needed.
Multi-Registry Support
Auto-authenticated access to Public, Yandex Cloud, AWS ECR, and GCP Artifact Registry out of the box.
Vault Integration
Secure credential management via HashiCorp Vault KV2 or local AES-256-GCM encrypted storage per artifact source.
Dependency Lock Files
Pin Python, Ansible, Molecule, and collection versions to diffusion.lock for fully reproducible builds.
Caching
Cache Ansible roles, collections, Docker images, and UV/Python packages between runs for 3–10× faster iteration.
CI/CD Ready
The --ci flag clones the repo inside the container, removes TTY requirements, and disables spinners for clean pipeline logs.
Artifact Management
Manage credentials for multiple private repositories with encrypted local storage or Vault — indexed as GIT_USER_N env vars.
Prerequisites
Required
- Docker containerized testing
- Go 1.25.4+ only if building from source
Optional CLIs
- Vault CLI HashiCorp Vault integration
- YC CLI Yandex Cloud registry
- AWS CLI AWS ECR registry
- gcloud CLI GCP registry
Recommended Terminal
- WezTerm or Ghostty for best Unicode/color support
- Nerd Fonts: FiraCode, JetBrains Mono, Hack
Installation
# Install
choco install diffusion
# Upgrade
choco upgrade diffusion
# Optional: enable signature and provenance verification
choco install cosign
Auto-detects architecture (AMD64 / ARM64 / ARM), verifies SHA256, adds diffusion to PATH.
go install github.com/Polar-Team/diffusion@latest
git clone https://github.com/Polar-Team/diffusion.git
cd diffusion
make build # binary -> bin/
make dist # Linux, macOS, Windows x AMD64/ARM64/ARM
make linux # Linux only
make darwin # macOS only
make windows # Windows only
Output binaries land in bin/ with descriptive names like diffusion-linux-amd64.
Quick Start
# 1. Scaffold a new Ansible role
diffusion role --init
# 2. Initialize and lock dependencies
diffusion deps init
diffusion deps lock
# 3. Run the full test cycle
diffusion molecule # converge
diffusion molecule --verify
diffusion molecule --lint
diffusion molecule --idempotence
diffusion molecule --destroy
diffusion molecule
Runs the Molecule testing workflow. Role name and org are auto-detected from meta/main.yml.
| Flag | Description |
|---|---|
diffusion molecule | Run converge (default) |
--converge [--tag "t1,t2"] | Apply role with optional Ansible tags |
--verify [--tag "check"] | Run verify tests |
--lint | Run yamllint + ansible-lint |
--idempotence [--tag "t"] | Idempotence check |
--destroy | Destroy test instances |
--wipe | Remove container + molecule folder |
--ci | CI/CD mode no TTY, no spinners, clones repo inside container |
--role / --org | Override auto-detected role/org |
--testsoverwrite | Overwrite molecule tests folder |
--converge, --verify, --lint, --idempotence, --destroy) are mutually exclusive only one at a time.Typical workflow
diffusion molecule --converge
diffusion molecule --verify
diffusion molecule --lint
diffusion molecule --idempotence
diffusion molecule --destroy
diffusion molecule --wipe
CI/CD mode
The --ci flag clones the repository inside the container instead of using volume mounts, eliminating TTY and permission issues in CI runners.
# GitHub Actions
- run: diffusion molecule --ci --converge
- run: diffusion molecule --ci --verify
# GitLab CI
script:
- diffusion molecule --ci --converge
- diffusion molecule --ci --verify
diffusion role
| Command | Description |
|---|---|
diffusion role | View current role configuration |
diffusion role --init | Initialize a new role interactively |
diffusion role add-role <name> --src <url> --version main | Add a role dependency |
diffusion role remove-role <name> | Remove a role dependency |
diffusion role add-collection community.general | Add a collection |
diffusion role remove-collection community.general | Remove a collection |
--scenario / -s <name> | Target a specific Molecule scenario (default: default) |
--init, the command displays current config. Use --init to scaffold a new role. If a role already exists, --init will warn you.diffusion deps
| Command | Description |
|---|---|
diffusion deps init | Add [dependencies] section to diffusion.toml |
diffusion deps lock | Resolve versions from PyPI/Galaxy and write diffusion.lock |
diffusion deps check | Verify lock file is up-to-date (exits 1 if not ideal for CI) |
diffusion deps resolve | Pretty-print all resolved versions from lock file |
diffusion deps sync | Write locked versions back to requirements.yml / meta.yml |
diffusion cache
| Command | Description |
|---|---|
diffusion cache enable | Enable caching for current role |
diffusion cache enable --docker | Also cache Docker images as tarballs |
diffusion cache enable --uv | Also cache UV/Python packages |
diffusion cache disable | Disable caching (preserves cache directory) |
diffusion cache clean | Remove cached artifacts for current role |
diffusion cache status | Show cache config and size |
diffusion cache list | List all cache directories across all roles |
diffusion artifact
| Command | Description |
|---|---|
diffusion artifact add <name> | Store encrypted credentials for a private repo |
diffusion artifact list | List all stored artifact sources |
diffusion artifact show <name> | Show source details (token masked) |
diffusion artifact remove <name> | Remove stored credentials and config entry |
Credentials are encrypted with AES-256-GCM using a machine-specific key derived from hostname:username. Stored in ~/.diffusion/secrets/<role>/<source> with 0700 directory permissions.
diffusion show
Displays all Diffusion configuration in a readable format.
diffusion show
⚙️ diffusion.toml
Created interactively on first run in your project directory. Run diffusion show to view current config.
[container_registry]
registry_server = "ghcr.io"
registry_provider = "Public"
molecule_container_name = "polar-team/diffusion-molecule-container"
molecule_container_tag = "latest-amd64"
[vault]
enabled = false
[yaml_lint]
extends = "default"
ignore = [".git/*", "molecule/**", "vars/*", "files/*"]
[yaml_lint.rules]
braces = { max-spaces-inside = 1, level = "warning" }
brackets = { max-spaces-inside = 1, level = "warning" }
comments = { min-spaces-from-content = 1 }
comments-indentation = false
octal-values = { forbid-implicit-octal = true }
[ansible_lint]
exclude_paths = ["molecule/default/tests/*.yml", "tests/test.yml"]
warn_list = ["meta-no-info", "yaml[line-length]"]
skip_list = ["meta-incorrect", "role-name[path]"]
[tests]
type = "local"
[cache]
enabled = false
[dependencies]
ansible = ">=10.0.0"
molecule = ">=24.0.0"
ansible_lint = ">=24.0.0"
yamllint = ">=1.35.0"
[dependencies.python]
min = "3.11"
max = "3.13"
pinned = "3.13"
[container_registry]
registry_server = "cr.yandex"
registry_provider = "YC"
molecule_container_name = "crp1234567890/diffusion-molecule-container"
molecule_container_tag = "latest-amd64"
[vault]
enabled = true
[[artifact_sources]]
name = "gitlab-private"
url = "https://gitlab.company.com"
use_vault = true
vault_path = "secret/data/artifacts"
vault_secret_name = "gitlab-creds"
vault_username_field = "username"
vault_token_field = "token"
[tests]
type = "diffusion"
[cache]
enabled = true
[container_registry]
registry_server = "us-docker.pkg.dev"
registry_provider = "GCP"
molecule_container_name = "my-project/my-repo/diffusion-molecule-container"
molecule_container_tag = "latest-amd64"
[vault]
enabled = false
[tests]
type = "local"
[cache]
enabled = false
Configuration reference
Container Registry
registry_server— e.g.ghcr.io,cr.yandexregistry_provider—Public|YC|AWS|GCPmolecule_container_name— image pathmolecule_container_tag— auto-detected arch tag
Tests Type
local— copy from projecttests/remote— clone from Git repos viaremote_repositoriesdiffusion— official diffusion-ansible-tests-role
Dependencies
- Version constraints for ansible, molecule, ansible_lint, yamllint
- Python
min/max/pinned(allowed: 3.11, 3.12, 3.13) - Collections:
[[dependencies.collections]] - Roles:
[[dependencies.roles]]
Vault
enabled = trueto activate- Requires
VAULT_ADDR+VAULT_TOKENenv vars - Pass to test containers via
molecule.ymlenv block
Passing credentials to test containers
Pass environment variables to test containers inside the Diffusion container via molecule.yml:
# molecule/default/molecule.yml
platforms:
- name: instance
image: your-registry/test-image:latest
env:
TOKEN: "${TOKEN}" # Registry token (YC, AWS, GCP)
VAULT_ADDR: "${VAULT_ADDR}" # Vault address
VAULT_TOKEN: "${VAULT_TOKEN}" # Vault token
🌐 Registry Support
| Provider | Registry Format | Auth Command | CLI Required |
|---|---|---|---|
| Public | ghcr.io, docker.io | None | None |
| Yandex Cloud | cr.yandex | yc iam create-token | YC CLI |
| AWS ECR | <account>.dkr.ecr.<region>.amazonaws.com | aws ecr get-login-password | AWS CLI |
| GCP Container Registry | gcr.io, us.gcr.io | gcloud auth print-access-token | gcloud CLI |
| GCP Artifact Registry | <region>-docker.pkg.dev | gcloud auth print-access-token | gcloud CLI |
GCP configuration examples
[container_registry]
registry_server = "us-docker.pkg.dev"
registry_provider = "GCP"
molecule_container_name = "my-project/my-repo/diffusion-molecule-container"
molecule_container_tag = "latest-amd64"
[container_registry]
registry_server = "gcr.io"
registry_provider = "GCP"
molecule_container_name = "my-project/diffusion-molecule-container"
molecule_container_tag = "latest-amd64"
📁 Project Structure
role-name/
├── defaults/ tasks/ handlers/ files/ templates/ vars/
├── meta/
│ └── main.yml # role metadata (auto-detected by diffusion)
├── scenarios/
│ └── default/
│ ├── converge.yml # convergence playbook
│ ├── verify.yml # verification tests
│ ├── molecule.yml # molecule configuration
│ └── requirements.yml # role & collection dependencies
├── diffusion.toml # diffusion configuration
├── diffusion.lock # locked dependency versions
└── .gitignore
🔄 CI/CD Integration
Use the --ci flag in CI/CD pipelines. It clones the repo inside the container (auto-detects git remote URL and commit SHA), removes -ti flags from docker exec, skips permission fixes, and disables spinner animations.
- name: Run Molecule tests
run: diffusion molecule --ci --converge
- name: Verify
run: diffusion molecule --ci --verify
- name: Check deps are locked
run: diffusion deps check
molecule-test:
script:
- diffusion molecule --ci --converge
- diffusion molecule --ci --verify
- diffusion deps check
📦 Dependency Management
Diffusion provides a comprehensive dependency management system that validates Python versions, resolves tool versions from PyPI, manages Ansible Galaxy collections, generates lock files, and dynamically passes pyproject.toml to the container.
Python version management
Only three Python versions are supported: 3.13, 3.12, 3.11. All versions use major.minor format only.
| Input | Normalized To |
|---|---|
pinned = "3.13.11" | pinned = "3.13" |
min = "3.11.9" | min = "3.11" |
pinned = "3.10" | ERROR — not an allowed version |
Only the pinned version is passed to the container as PYTHON_PINNED_VERSION.
Tool version constraints
Specify constraints in diffusion.toml. Supported operators: >=, <=, ==, >, <.
[dependencies]
ansible = ">=13.0.0"
molecule = ">=24.0.0"
ansible_lint = ">=24.0.0"
yamllint = ">=1.35.0"
[dependencies.python]
min = "3.11"
max = "3.13"
pinned = "3.13"
[[dependencies.collections]]
name = "community.general"
version = ">=7.4.0"
Lock file structure
version: "1.0"
generated: "2024-12-26T10:00:00Z"
hash: "abc123..."
python:
min: "3.11"
max: "3.13"
pinned: "3.13"
tools:
- name: ansible
version: ">=13.0.0"
resolved_version: "13.1.0"
type: tool
source: pypi
collections:
- name: community.general
version: ">=7.4.0"
resolved_version: "7.5.0"
type: collection
source: galaxy
python_deps:
docker: "7.1.0"
requests: "2.32.3"
roles:
- name: geerlingguy.docker
version: ">=7.0.0"
resolved_version: "7.4.1"
type: role
source: galaxy
The hash is computed from all dependency names, versions, and Python config. diffusion deps check recomputes and compares it.
Version compatibility
Diffusion automatically validates tool compatibility with Python versions. If you specify incompatible versions, it warns and adjusts.
| Python | Ansible | Molecule | ansible-lint |
|---|---|---|---|
| 3.13 | 8–13 | 5–25 | 6–24 |
| 3.12 | 8–13 | 5–25 | 6–24 |
| 3.11 | 8–13 | 5–25 | 6–24 |
Dependency priority
When the same dependency is specified in multiple places:
diffusion.toml(highest priority)requirements.ymlmeta/main.yml(lowest priority)
Workflow
diffusion deps init # add [dependencies] to diffusion.toml
diffusion deps lock # resolve from PyPI/Galaxy, write diffusion.lock
diffusion deps resolve # pretty-print resolved versions
diffusion deps check # verify lock is up-to-date (CI gate)
diffusion deps sync # write locked versions back to requirements.yml
⚡ Cache Feature
The cache feature persists the .ansible directory from the Molecule container to your local filesystem, significantly speeding up subsequent runs by caching downloaded collections, roles, Docker images, and Python packages.
How it works
- A unique cache ID is generated for your role
- Cache directory created at
~/.diffusion/cache/role_<cache_id>/ - Subdirectories
roles/andcollections/are mounted to/root/.ansible/rolesand/root/.ansible/collectionsin the container - On subsequent runs, artifacts are reused instead of re-downloaded
Performance impact
| Without Cache | With Cache | |
|---|---|---|
| First run | 3–5 minutes | Same (builds cache) |
| Subsequent runs | 3–5 minutes | 30s – 1 min |
| Network | ~50 MB download | Minimal |
Configuration
[cache]
enabled = true
cache_id = "a1b2c3d4e5f6g7h8"
# cache_path = "custom/path" # optional override
Docker integration
docker run ... \
-v ~/.diffusion/cache/role_<id>/roles:/root/.ansible/roles \
-v ~/.diffusion/cache/role_<id>/collections:/root/.ansible/collections \
...
Best practices
- Enable cache during active development for faster iterations
- Clean cache periodically with
diffusion cache clean - Disable cache in CI/CD for clean builds
- Share
cache_idin team docs for consistent caching
Directory structure
~/.diffusion/
└── cache/
├── role_a1b2c3d4e5f6g7h8/
│ ├── collections/
│ └── roles/
└── role_9f8e7d6c5b4a3210/
├── collections/
└── roles/
🔑 Artifact Management
Diffusion supports managing multiple private artifact repository credentials with secure encrypted storage. Credentials can be stored locally (encrypted) or in HashiCorp Vault.
Security
Encryption
- Algorithm: AES-256-GCM
- Key: SHA-256 of
hostname:username:diffusion-artifact-secrets - Nonce: randomly generated per operation
- Storage:
~/.diffusion/secrets/<role>/<source> - Permissions: 0600 (owner only)
Properties
- Machine-specific — cannot decrypt on another machine
- User-specific — each user has own key
- Authenticated encryption (GCM)
- Key derived on-demand, never stored
Adding credentials
$ diffusion artifact add my-private-repo
Enter URL for my-private-repo: https://artifacts.example.com
Store credentials in Vault? (y/N): n
Enter Username: myuser
Enter Token/Password: ********
Credentials saved (encrypted in ~/.diffusion/secrets/<role>/my-private-repo)
[[artifact_sources]]
name = "my-private-repo"
url = "https://artifacts.example.com"
use_vault = false
$ diffusion artifact add vault-repo
Enter URL: https://vault-artifacts.example.com
Store credentials in Vault? (y/N): y
Enter Vault path: secret/data/prod
Enter Vault secret name: vault-repo
Enter Username Field (default: username): git_username
Enter Token Field (default: token): git_token
[[artifact_sources]]
name = "vault-repo"
url = "https://vault-artifacts.example.com"
use_vault = true
vault_path = "secret/data/prod"
vault_secret_name = "vault-repo"
vault_username_field = "git_username"
vault_token_field = "git_token"
[vault]
enabled = true
[[artifact_sources]]
name = "dev-repo"
url = "https://dev.example.com"
use_vault = false # stored locally
[[artifact_sources]]
name = "prod-repo"
url = "https://prod.example.com"
use_vault = true # stored in Vault
vault_path = "secret/data/prod"
vault_secret_name = "artifacts"
vault_username_field = "git_username"
vault_token_field = "git_token"
[vault]
enabled = true
Environment variables
When running molecule, Diffusion sets indexed environment variables for each source:
GIT_USER_1=user1 GIT_PASSWORD_1=token1 GIT_URL_1=https://repo1.example.com
GIT_USER_2=user2 GIT_PASSWORD_2=token2 GIT_URL_2=https://repo2.example.com
# ... up to GIT_*_10 (configurable via MaxArtifactSources)
Using in Ansible
- name: Clone from private repository
ansible.builtin.git:
repo: "{{ lookup('env', 'GIT_URL_1') }}"
dest: /opt/myapp
version: main
environment:
GIT_USERNAME: "{{ lookup('env', 'GIT_USER_1') }}"
GIT_PASSWORD: "{{ lookup('env', 'GIT_PASSWORD_1') }}"
Troubleshooting
- Cannot decrypt after moving machines — credentials are machine-specific, re-add them
- Permission denied —
chmod 700 ~/.diffusion/secrets - Vault connection failed — verify
VAULT_ADDR,VAULT_TOKEN, and path/secret config
🔨 Building from Source
Requires Go 1.21+ and Make. Go supports cross-compilation out of the box — build for any platform from any platform.
Main targets
| Command | Description |
|---|---|
make build | Build for current platform |
make dist | Build for all platforms |
make linux | All Linux architectures |
make darwin | All macOS architectures |
make windows | All Windows architectures |
make test | Run unit tests |
make clean | Remove build artifacts |
Platform-specific targets
# Linux
make linux-amd64 # x86_64
make linux-arm64 # ARM64, Raspberry Pi 4+
make linux-arm # Raspberry Pi 3, older ARM
# macOS
make darwin-amd64 # Intel Macs
make darwin-arm64 # Apple Silicon (M1/M2/M3)
# Windows
make windows-amd64 # Standard PCs
make windows-arm64 # Surface Pro X, etc.
make windows-arm # Older ARM devices
Output
bin/
├── diffusion-linux-amd64
├── diffusion-linux-arm64
├── diffusion-linux-arm
├── diffusion-darwin-amd64
├── diffusion-darwin-arm64
├── diffusion-windows-amd64.exe
├── diffusion-windows-arm64.exe
└── diffusion-windows-arm.exe
Build flags
The Makefile uses -s -w (strip symbol table and DWARF info) and injects version via -X. You can specify a version: make VERSION=1.0.0 dist.
Manual build (without Make)
GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o bin/diffusion-linux-amd64 .
GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w" -o bin/diffusion-darwin-arm64 .
GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o bin/diffusion-windows-amd64.exe .
CI/CD build examples
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: '1.21'
- run: make dist
- uses: actions/upload-artifact@v3
with:
name: binaries
path: bin/
build:
image: golang:1.21
script:
- make dist
artifacts:
paths:
- bin/
✅ Binary Verification
All releases are signed with Cosign and include SLSA Level 3 provenance for supply chain security.
Security layers
- SHA256 checksums — verify file integrity
- Cosign signatures — verify authenticity (keyless via Sigstore)
- SLSA Level 3 provenance — verify build process and supply chain
Quick verification
# 1. Verify checksum
sha256sum --check SHA256SUMS --ignore-missing
# 2. Verify Cosign signature
cosign verify-blob \
--certificate diffusion-linux-amd64.tar.gz.pem \
--signature diffusion-linux-amd64.tar.gz.sig \
--certificate-identity-regexp="https://github.com/Polar-Team/diffusion" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
diffusion-linux-amd64.tar.gz
# 3. Verify SLSA provenance
slsa-verifier verify-artifact diffusion-linux-amd64.tar.gz \
--provenance-path multiple.intoto.jsonl \
--source-uri github.com/Polar-Team/diffusion \
--source-tag v1.0.0
Platform-specific
sudo apt install cosign gh
# or: sudo dnf install cosign gh
# Install slsa-verifier from GitHub releases
cosign verify-blob \
--certificate diffusion-linux-amd64.tar.gz.pem \
--signature diffusion-linux-amd64.tar.gz.sig \
--certificate-identity-regexp="https://github.com/Polar-Team/diffusion" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
diffusion-linux-amd64.tar.gz
brew install cosign gh slsa-verifier
cosign verify-blob \
--certificate diffusion-darwin-arm64.tar.gz.pem \
--signature diffusion-darwin-arm64.tar.gz.sig \
--certificate-identity-regexp="https://github.com/Polar-Team/diffusion" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
diffusion-darwin-arm64.tar.gz
choco install cosign gh
cosign verify-blob `
--certificate diffusion-windows-amd64.zip.pem `
--signature diffusion-windows-amd64.zip.sig `
--certificate-identity-regexp="https://github.com/Polar-Team/diffusion" `
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" `
diffusion-windows-amd64.zip
SLSA Level 3
- Build integrity — isolated and tamper-proof
- Provenance — generated automatically
- Non-falsifiable — cryptographically signed
- Dependency tracking — recorded in provenance
🔒 Unix Permissions
Docker containers run as root (required for Docker-in-Docker), which causes permission issues on Linux/macOS. Diffusion uses a hybrid approach.
How it works
Main Molecule Container
Runs as ROOT (required for DinD). After operations, ownership is fixed inside the container: chown -R UID:GID /opt/molecule.
AnsibleGalaxyInit Container
Runs with user mapping (--user UID:GID). Creates role structure with correct ownership from the start.
Windows
Containers run as root (default). No permission fixes needed due to Windows filesystem model.
Permission fixing
// Runs inside container where we have root privileges
chownCmd := fmt.Sprintf("chown -R %d:%d /opt/molecule", uid, gid)
dockerExecInteractiveHide(RoleFlag, "/bin/sh", "-c", chownCmd)
Called after: ansible-galaxy role init, molecule converge, and all molecule operations.
Troubleshooting
- Molecule folder owned by root — permission fix didn't run; check logs
- "operation not permitted" — fix now runs inside container (should not occur)
- Cannot access Docker inside container — ensure main container runs as root (no --user flag)
📌 Role Version Constraints
Roles support version constraints across three files: diffusion.toml (constraints), diffusion.lock (constraints + resolved), requirements.yml (resolved versions).
Constraint logic
| Input Constraint | Resolved Version | Stored in diffusion.toml |
|---|---|---|
| (empty) | 1.2.3 | >=1.2.3 |
latest | 1.2.3 | >=1.2.3 |
main | 1.2.3 | >=1.2.3 |
>=1.0.0 | 1.2.3 | >=1.0.0 |
==1.0.0 | 1.0.0 | ==1.0.0 |
Adding a role with constraints
diffusion role add-role geerlingguy.docker \
--src https://github.com/geerlingguy/ansible-role-docker.git \
--version ">=6.0.0" \
--scenario default
This resolves the latest version from Galaxy, adds to requirements.yml with the resolved version, and adds to diffusion.toml with the constraint.
Git version resolution
For git repositories, Diffusion fetches all tags via git ls-remote, compares each against the constraint, and returns the latest matching tag. Supports >=, <=, ==, >, <.
File structure
# diffusion.toml — stores constraints
[[dependencies.roles]]
name = "default.geerlingguy.docker"
src = "https://github.com/geerlingguy/ansible-role-docker.git"
scm = "git"
version = ">=6.0.0"
# diffusion.lock — stores both
roles:
- name: geerlingguy.docker
version: ">=6.0.0"
resolved_version: "6.1.0"
# requirements.yml — stores resolved
roles:
- name: geerlingguy.docker
src: https://github.com/geerlingguy/ansible-role-docker.git
scm: git
version: "6.1.0"
🔄 Migration Guide
Migrating from single-URL artifact configuration to the new multi-source structure.
What changed
url = "https://artifacts.example.com"
[vault]
enabled = true
secret_kv2_path = "secret/data/git"
secret_kv2_name = "credentials"
username_field = "git_username" # REMOVED — now per-source
token_field = "git_token" # REMOVED — now per-source
[[artifact_sources]]
name = "primary"
url = "https://artifacts.example.com"
use_vault = true
vault_path = "secret/data/git"
vault_secret_name = "credentials"
vault_username_field = "git_username" # now per-source
vault_token_field = "git_token" # now per-source
[vault]
enabled = true # simplified — no field names here
Migration options
Automatic
Delete diffusion.toml and run diffusion molecule --role test --org test. Follow the interactive prompts.
Manual
Edit diffusion.toml directly: replace url with [[artifact_sources]] blocks, move Vault field names to per-source config.
Backward compatibility
The old configuration still works but shows a deprecation notice. Environment variables (GIT_USER_1, etc.) remain unchanged — Ansible playbooks don't need updates.
Secrets storage path change
- Old:
~/.diffusion/<source>_artifact_secrets - New:
~/.diffusion/secrets/<role>/<source>
Breaking changes
- Vault field names (
username_field,token_field) moved from[vault]to per-source[[artifact_sources]] diffusion rolewithout--initnow displays config instead of prompting to initialize