Vendoring Component Versions
Vendoring Component Versions is a complementary technique that automates copying component versions from multiple external sources into your repository. This works with any deployment strategy—Continuous Version Deployment or Git Flow—and can be combined with any folder organization approach.
Vendoring gives teams local control over external dependencies by bringing component code in-house while maintaining metadata about origin and lineage. Whether you use Folder-Based Versioning, Release Tracks, or Strict Version Pinning, vendoring provides predictable update cycles and the ability to apply custom modifications when necessary.
You will learn
- Why Atmos makes explicit what other tools do implicitly (just-in-time cloning)
- Operational benefits: visibility, audit trail, emergency agility, explicit divergence
- Developer experience benefits: searchability, readability, IDE support
- How to converge with upstream when it makes sense and diverge when needed
- The pragmatic approach that emerged from countless projects
Philosophy: Explicit Over Implicit
Most tools that "pin to remote sources" actually do this behind the scenes:
- Clone the remote source to a temporary folder (just-in-time vendoring)
- Point Terraform/tooling at that temporary folder
- Clean up the folder after execution
Atmos makes this process explicit:
- Vendor upstream components with
atmos vendor pull - Commit the vendored code to your repository
- Pin components to those vendored folders
- Update vendored code on your schedule
The result is functionally the same, but with critical advantages for operations and developer experience.
Why We Vendor: Lessons from Countless Projects
This approach emerged from real operational pain across countless projects. We tried pure remote sourcing—it created productivity blockers:
The Coordination Nightmare: Cross-cutting changes required opening dozens of PRs across multiple repositories. If you discovered a problem at any step, you started over. Or you took shortcuts (pinning to branches instead of versions), creating technical debt to clean up later.
The Developer Experience Problem: When everything is a remote reference, developers can't search the codebase for definitions, IDE navigation breaks ("Go to definition" fails), and understanding requires dereferencing dozens of sources. The cognitive overhead compounds quickly.
The Emergency Response Problem: Security patches get blocked waiting for upstream review and release cycles. When minutes matter, multi-repository coordination kills agility.
Pure DRY leads to complexity rashes. The pragmatic approach: vendor explicitly, converge with upstream when it makes sense, diverge when you need to.
Benefits of Explicit Vendoring
Operational Benefits
Visibility via Git Diff:
When you update vendored dependencies, git diff shows the actual code changes—not just version number bumps. This makes code review meaningful and catches breaking changes before deployment.
Immutable Audit Trail: Every vendored update is a commit in your repository. You have a complete, immutable record of what code ran when, satisfying compliance requirements without additional tooling.
Emergency Agility: Need to patch a vulnerability? Make changes directly in the vendored folder and deploy immediately. No waiting for upstream PRs, reviews, or release cycles. Re-sync with upstream when the dust settles.
Explicit Divergence Signaling: When you need to diverge from upstream (emergency patches, business-specific changes), disable the vendoring config for that component. This clearly signals to your team: "we've intentionally diverged here."
Developer Experience Benefits
Searchable Codebase:
grep and IDE search work across all vendored components. Finding where something is defined takes seconds, not minutes of jumping between repositories.
Readable Code: Open files and understand implementation without dereferencing remote sources. The code is right there, readable and navigable.
IDE Functionality Works: "Go to definition", "Find references", and other IDE features work across vendored components. Developer tools function as intended.
Reduced Cognitive Load: No constant context switching to external repositories. Everything needed to understand the system is in one place.
Better Onboarding: New team members can explore the actual code to learn how things work, not just read abstract documentation or hunt through remote references.
Vendoring is exceptionally valuable for AI-powered editors and coding assistants (e.g., Claude Code, Cursor, etc.). When components are vendored locally, AI tools have full access to the actual implementation code, enabling them to:
- Understand component behavior and dependencies accurately
- Provide context-aware suggestions and completions
- Catch integration issues before deployment
- Generate infrastructure code that correctly uses vendored components
Remote references force AI tools to work with limited context or make assumptions. Vendored code gives AI the complete picture.
Use Cases
Use the Vendoring Components pattern when:
- You need predictable update windows for third-party components
- Compliance requirements mandate code auditing and approval
- You need to apply custom patches to upstream components
- Network restrictions limit access to external repositories
- You want resilience against upstream availability issues
- You need consistent versioning across all environments without external dependencies
- Upstream cadence doesn't match your release schedule
Problem
Direct dependencies on external repositories create several challenges:
- Upstream Breaking Changes: Unexpected changes can break deployments
- Availability Risks: External sources may become unavailable
- Audit Challenges: Difficult to review all code changes in external dependencies
- Timing Mismatches: Upstream release schedules may not align with your needs
- Patching Limitations: Cannot modify external code without forking
- Network Dependencies: Requires internet access during deployment
Vendoring addresses these issues by bringing code under local control while maintaining traceability.
Solution
Copy external component code into your repository with clear metadata about its origin, version, and any local modifications. Use Atmos's vendor command to manage the process systematically.
Core Principles
- Local Copies: All external code is copied into your repository
- Origin Tracking: Maintain metadata about where code came from
- Bulk Updates: Update multiple components together in controlled windows
- Intentional Divergence: Clearly mark and track local modifications
- Audit Trail: Document all vendor updates and changes
Implementation with Atmos
Atmos provides built-in vendoring support through the vendor.yaml manifest and atmos vendor command.
Basic Vendor Configuration
Atmos vendor manifests support Go template syntax in source and targets fields. The template is executed with the source specification as the data context, allowing you to reference any field defined in that source entry (like component, version, source, etc.) using {{.FieldName}} syntax.
This creates DRY (Don't Repeat Yourself) configurations where you define values once and reference them in multiple places. For example, {{.Version}} in the source URL will be replaced with the value from the version field.
vendor.yaml
Template Variables in Vendor Manifests
Atmos vendor manifests support Go template syntax in source and targets paths. The template is executed with the vendor source specification as the data context, providing access to all fields defined in that source entry.
Available Template Variables:
| Variable | Description | Example Value |
|---|---|---|
{{.Component}} | Component name from the component: field | vpc, eks, rds |
{{.Version}} | Version from the version: field | 2.1.0, main, v3.5.0 |
{{.Source}} | Full source URL before template expansion | github.com/cloudposse/... |
{{.File}} | File path if specified | component.yaml |
Using {{.Component}} for DRY Configuration:
The {{.Component}} variable creates programmatically consistent configurations where the component name drives both source and target paths:
vendor.yaml
This pattern eliminates duplication and makes bulk operations easier. When you need to change a naming convention or base path, you update it once in the template rather than in every source entry.
Advanced Vendor Configuration
vendor.yaml
Tracking Vendored Components
The vendor.yaml file serves as your vendor manifest, documenting all component sources and versions:
vendor.yaml (vendor manifest)
The vendor.yaml file IS your vendor manifest. It tracks:
- Source repository and exact version for each component
- Target location where the component is vendored
- Included/excluded paths to control what gets vendored
- Tags for organizing and filtering components
To see what version is currently vendored, check the vendor.yaml file.
Vendoring Workflow
1. Initial Vendoring
# Pull all configured components
atmos vendor pull
# Pull specific component
atmos vendor pull --component vpc
# Pull with specific version override
atmos vendor pull --component vpc --version 2.2.0
# Dry run to see what would be vendored
atmos vendor pull --dry-run
2. Tracking Local Modifications
When making local changes to vendored components:
components/terraform/vpc/LOCAL_MODIFICATIONS.md
3. Bulk Updates
Perform controlled bulk updates using Atmos vendor commands:
# Update all vendored components
atmos vendor pull
# Update specific component
atmos vendor pull --component vpc
# Update with specific version
atmos vendor pull --component vpc --version v2.2.0
# Dry run to preview changes
atmos vendor pull --dry-run
Track vendor updates in your vendor manifest:
# vendor.yaml - Update component version
spec:
sources:
- component: vpc
source: "github.com/cloudposse/terraform-aws-vpc.git///?ref={{.Version}}"
version: "2.2.0" # Updated from 2.1.0
targets:
- "components/terraform/vpc"
4. Handling Divergence
When intentionally diverging from upstream:
vendor.yaml
Diverging from Upstream
When you need to diverge from upstream (emergency patches, business-specific changes), Atmos provides a clear path:
1. Make Local Changes: Edit the vendored component directly in your repository. The changes are immediately visible in git diff.
2. Disable Vendoring for That Component:
Comment out or remove the component from vendor.yaml to signal intentional divergence:
vendor.yaml
3. Document the Divergence:
Create a LOCAL_MODIFICATIONS.md file in the component directory explaining what changed and why.
4. Reconverge When Ready: When upstream incorporates your changes or you're ready to drop local modifications:
- Re-enable the vendoring config
- Run
atmos vendor pullto sync with upstream - Review and resolve any conflicts
This explicit workflow ensures divergence is visible, documented, and intentional—not hidden or accidental.
Drawbacks
The pattern also has limitations:
- Maintenance Burden: You own security patches and bug fixes
- Repository Size: Vendored code increases repository size
- Update Lag: May fall behind upstream improvements
- Merge Complexity: Reconciling local changes with updates
- Tooling Requirements: Need processes for vendor management
Best Practices
1. Maintain Clear Lineage
Always document in vendor.yaml where code came from:
# Track all component sources in vendor.yaml
spec:
sources:
- component: vpc
source: "github.com/cloudposse/terraform-aws-vpc.git///?ref={{.Version}}"
version: "2.1.0"
# Use comments to document any local modifications
# Modified: Added compliance tags, custom security groups
2. Document Divergence
Clearly document why and how you've diverged:
# Divergence Documentation
## Component: VPC
**Diverged**: Yes
**Date**: 2024-01-21
**Reason**: Compliance requirements
### Changes Made:
1. Added mandatory compliance tags
2. Modified security group rules
3. Added custom outputs for monitoring
### Update Strategy:
- Manual review required
- Cannot auto-update due to custom changes
- Patches must be manually applied
### Future Plans:
- Working with upstream to incorporate changes
- Target convergence: Q2 2024
Rollback Strategy
Vendoring provides multiple rollback approaches:
Option 1: Revert to Previous Vendored Version
# Check Git history for the vendored component
git log --oneline components/terraform/vpc/
# Revert to a previous commit
git checkout <previous-commit> -- components/terraform/vpc/
# Or use Git to revert the vendor pull
git revert <vendor-update-commit>
# Validate the rollback
atmos validate component vpc --stack prod-us-east-1
# Apply the rollback
atmos terraform apply vpc --stack prod-us-east-1
Option 2: Re-vendor Previous Version
# vendor.yaml - Specify the previous version
spec:
sources:
- component: vpc
source: "github.com/cloudposse/terraform-aws-vpc.git"
version: "2.0.0" # Was 2.1.0, rolling back
targets:
- "components/terraform/vpc"
# Re-vendor the previous version
atmos vendor pull --component vpc
# This will overwrite local changes - use with caution!
Option 3: Use Version Control for Rollback
# If vendored components are committed to Git
git diff HEAD~1 components/terraform/vpc/ # Review changes
git checkout HEAD~1 -- components/terraform/vpc/ # Rollback
If you have local modifications, ensure they're preserved during rollback or reapplied afterward.
Summary
Vendoring Components provides maximum control over external dependencies at the cost of increased maintenance responsibility. It's ideal for organizations with strict compliance requirements, those needing predictable update windows, or teams that must maintain custom patches. While it increases repository size and maintenance burden, the benefits of local control, audit capability, and resilience often justify these trade-offs for critical infrastructure components.
Vendoring is about taking ownership of your dependencies. Use it when external code is critical to your infrastructure and you need full control over when and how it changes.
Related Patterns
- Versioning Schemes - Works with any scheme - vendor to SemVer folders, maturity tracks, etc.
- Folder-Based Versioning - Version through repository structure
- Release Tracks/Channels - Abstract version management
- Component Catalog - Organizing vendored components
- Component Inheritance - Extending vendored components