12 additions/updates across 5 best-practice files: - docker-uid-matching: userdel simplification, SSH agent socket UID match - debugging: GIT_SSH_COMMAND scope limitation - test-driven-development: subprocess mock gotcha, routing callables, Pydantic v2 field_validator defaults, sys.exit at module level - spec-driven-development: multi-agent orchestration practices (commit WIP, self-verify, import conventions, assembly budget) - validation: test pre-commit hooks after adding dependencies Source: agent-runtimes/memory/ (decisions, gotchas-docker, gotchas-python, process-lessons, m1/m2/m3 reflections) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.6 KiB
Validation & Deployment
Validate Locally, Deploy Once
The single biggest time sink across projects is "deploy first, validate later." Real-world stats from a 9-milestone infrastructure project showed 50-60% of commits were fixes that could have been caught locally.
Always validate before pushing:
helm templatefor Helm chart valueskustomize build(orkubectl kustomize) for Kustomize appskubectl apply --dry-run=serverfor K8s naming/schema issuesdocker run <app> validate-configurationfor apps that support it (Authelia, Homepage, etc.)docker inspectfor unfamiliar container images before writing init containers- Lint/typecheck/test for application code
Batch fixes locally, push once. Each push-sync-crash-fix cycle wastes minutes and clutters Git history.
Test the Full Chain Immediately
After wiring up any new service or endpoint, test end-to-end from the user's perspective right away. Don't assume intermediate steps working means the whole chain works.
curl --resolve domain:443:<ip> https://domainto test bypassing DNS/proxy layers- Test from the actual consumer (not same-namespace test pods for network policies)
- Test DNS resolution after deploying FQDN-based policies
Pre-Flight Checks
Before starting a deploy or automation phase:
- Verify SSH keys are loaded (
ssh -T git@<host>) - Confirm environment variables and credentials are available
- Check that the target environment is in the expected state
- Verify DNS records resolve as expected
Scripts That Change Config Must Self-Verify
After updating and restarting a service, the script should test that the change actually took effect (e.g., curl an API endpoint, check a config value). A "success" message without verification hides failures.
Check Container Image Runtime Requirements First
Before writing deployment manifests (StatefulSets, Deployments, init containers), check the image's runtime expectations: UID it runs as, writable directories it needs, filesystem layout. Use docker inspect or image documentation.
Modern images often run as non-root with specific writable directory requirements that aren't obvious from docs alone. Discovering these at deploy time wastes an entire push-crash-fix cycle per missed requirement.
Verify Counts and Summaries Mechanically
After editing specification or documentation files that include summary counts (e.g., "14 requirements"), verify them with grep or wc rather than counting manually. Manual counting of dozens of items is error-prone and produces incorrect summaries that erode trust in the documentation.
Test Pre-Commit Hooks Manually After Adding Dependencies
Run bash .githooks/pre-commit (or your hook path) manually after adding new dependencies or changing test imports. Hidden virtual environments (.venv/) that the hook discovers before system Python can cause ModuleNotFoundError at commit time even though tests pass from the terminal. Discovering hook failures during a real commit wastes debugging effort on environment issues rather than code issues. After adding a dependency, check all Python environments: find . -name "activate" -o -name "pytest" to discover venvs, and install into each.
Order Multi-Step Migrations Carefully
When performing multi-step changes on remote systems (port changes, firewall rules, service migrations), plan explicit ordering to avoid lockout:
- Open the new path first (new port, new firewall rule)
- Migrate the service to use the new path
- Add redirects or backward-compatibility rules
- Remove the old path
Doing all steps at once risks losing access if any step fails. Plan the ordering upfront, not mid-deploy.