Multi-Repository Setup
Audience: DevOps teams managing infrastructure-as-code across multiple repositories. You have separate repos for Terraform modules, Ansible playbooks, Helm charts, and deployment configs. You want to understand how to register, pin versions, and synchronize them in CI/CD.
Multi-repo is a core strata capability. Instead of one monorepo, you register multiple repositories
and reference them with @repo_name/path syntax. This guide covers the practical workflow.
Why Multi-Repo?
Single repo problems:
Terraform modules, Ansible playbooks, and deployment configs all change at different cadences
Large monorepos are slow to clone and build
Different teams own different repos (infrastructure, platform, config)
Versioning is implicit (what commit do we use?)
Multi-repo solution:
Each repo has its own change cadence, versioning, and ownership
Deployment configs explicitly reference which version to use per repo
Repositories are cloned once, reused across multiple deployments
Version pinning is environment-specific (dev uses main, prd uses tagged releases)
Repository Registration
Registering a repository
Register a repository once per workspace. Two types: remote git and local.
Remote git repository
strata repo add infra https://github.com/org/xyz-infrastructure.git --branch main --clone
Option |
Default |
Purpose |
|---|---|---|
|
|
Default branch to track |
|
false |
Clone immediately after registering (otherwise: register only) |
Auto-detection: Remote URLs are detected by prefix (https://, git@, etc.) and registered
as type gitops. The repository is cloned to .strata/repos/infra/ by default.
Local repository (already on disk)
strata repo add platform C:/repos/xyz-platform
Or with explicit type:
strata repo add platform C:/repos/xyz-platform --type local
When to use: Shared repos already cloned to the developer machine, or monorepo split across multiple local folders.
Listing registered repositories
strata repo list
strata repo list --name infra # single repo
Output:
Repositories registered in workspace: my-platform
✅ infra (git) https://github.com/org/xyz-infrastructure.git
Status: cloned at C:\repos\xyz-config\.strata\repos\infra
Branch: main
Behind: 0
✅ platform (git) https://github.com/org/xyz-platform-modules.git
Status: cloned at C:\repos\xyz-config\.strata\repos\platform
Branch: develop
Behind: 5 commits
✅ shared (local) C:\repos\xyz-shared
Status: on disk
Syncing repositories
Clone all registered remote repos (or update existing clones):
strata repo sync
strata repo sync --name infra # single repo
strata repo sync --name infra --force # hard-reset if dirty
--force hard-resets the working tree if there are uncommitted changes. Use with caution.
Removing a repository
strata repo remove infra
strata repo remove infra --purge # also delete the clone
Repository Status and Version Tracking
Check repository status
strata repo status
strata repo status --name infra
strata repo status --output json
Output:
Repository Status
─────────────────
✅ infra [main → origin/main]
Tags:
Release: v2.3.0 (7 days ago, abc1234)
Quality: tested (2 days ago, def5678)
Ahead: 0, Behind: 2
✅ platform [develop → origin/develop]
Tags:
Release: v1.5.0 (21 days ago, ghi9abc)
Quality: tested-prd (1 day ago, jkl2def)
Ahead: 3, Behind: 0
Key columns:
[branch → remote/branch] — your local branch and what it’s tracking
Release tag — latest semver tag (used for pinning versions)
Quality tag — optional deployment gate tag (e.g., “tested”, “approved”)
Ahead/Behind — commit count vs. tracking remote
Referencing Repositories in YAML
The @repo_name syntax
Reference files in registered repos using @repo_name/path notation:
# deployments/deploy-prd.yaml
apiVersion: strata.huybrechts.xyz/v1
kind: deployment
spec:
workspace:
name: platform
source:
repository: platform # reference the repo by name
source_path: workspace.yaml # relative path within the repo
provisioners:
- name: terraform
provisioner: terraform
source:
repository: infra # different repo for Terraform
source_path: terraform/prod
environment:
- @infra/environments/prd.yaml # environment file from infra repo
- @shared/common/variables.yaml # shared variables from another repo
Resolution at build time
When you run strata build run -f deployments/deploy-prd.yaml, strata:
Looks up
infrainsolution.spec.repositoriesFinds the local clone path:
.strata/repos/infra/Resolves
terraform/prodrelative to that pathGenerates build artifacts with the resolved files
Benefits
Decoupled updates: Update the Terraform repo without touching deployment configs
Version pinning: Specify which version each env uses (see below)
Re-use: Share common files across multiple deployments
Security: Separate access controls per repository (git permissions)
Version Pinning and Promotion
Pin a repository to a specific version
Use git tags to mark stable versions. In your environment config, pin the tag:
# environments/env-prd.yaml
apiVersion: strata.huybrechts.xyz/v1
kind: environment
spec:
repositories:
- name: infra
version: v2.3.0 # pin to tagged release
- name: platform
version: tested-20260620 # pin to quality-gate tag
- name: shared
version: main # or use branch name (less stable)
At build time, strata checks out the specified version (tag or branch) before resolving file paths.
Promotion workflow
Development: Use branches (most recent code)
# env-dev.yaml
repositories:
- name: infra
version: develop
- name: platform
version: develop
Staging: Use quality-gate tags (tested code)
# env-stg.yaml
repositories:
- name: infra
version: tested
- name: platform
version: approved-for-staging
Production: Use release tags (versioned, stable)
# env-prd.yaml
repositories:
- name: infra
version: v2.3.0
- name: platform
version: v1.5.0
Tagging strategy
Use this pattern:
Tag Pattern |
Meaning |
When to create |
|---|---|---|
|
Release tag (semantic versioning) |
When merging to main, after approval |
|
Quality gate tag |
After CI passes (tests, linting, security scan) |
|
Promotion tag |
Manual step before deploying to production |
|
Branch (implicit version) |
Always points to latest code |
Example:
# In your IaC repo CI/CD pipeline:
# After tests pass:
git tag -a tested-$(date +%Y%m%d) -m "Passed automated tests"
git push origin tested-$(date +%Y%m%d)
# After manual approval:
git tag -a v2.3.0 -m "Release v2.3.0"
git push origin v2.3.0
# Or just update the moving tag:
git tag -d tested && git tag -a tested -m "Latest tested build"
git push -f origin tested
CI/CD Integration
Syncing repositories in your pipeline
Before deploying, sync all registered repos to the latest version:
# GitHub Actions
- name: Sync repositories
run: strata repo sync
- name: Deploy
run: strata deploy run -f deployments/deploy-prd.yaml --force
# Azure Pipelines
- script: strata repo sync
displayName: Sync repositories
- script: strata deploy run -f deployments/deploy-prd.yaml --force
displayName: Deploy
Checking out a specific repository version
If your deployment pins a version, strata checks it out automatically. But you can also force it in CI/CD:
# Explicit checkout (useful for debugging or manual promotion)
cd .strata/repos/infra
git checkout v2.3.0 # checkout the pinned version
cd - && strata deploy run -f deployments/deploy-prd.yaml
Example: Multi-stage promotion pipeline
# azure-pipelines.yml
trigger:
- main
stages:
- stage: Build
jobs:
- job: BuildAndTest
steps:
- script: strata build run -f deployments/deploy-dev.yaml
- script: strata build sbom -f deployments/deploy-dev.yaml --audit --fail-on HIGH
- stage: DeployDev
dependsOn: Build
jobs:
- job: Deploy
steps:
- script: strata repo sync
- script: strata deploy run -f deployments/deploy-dev.yaml --force
- stage: DeployStaging
dependsOn: DeployDev
jobs:
- deployment: DeployToStaging
environment: staging
strategy:
runOnce:
deploy:
- script: strata repo sync
- script: strata deploy run -f deployments/deploy-stg.yaml --force
- stage: DeployProduction
dependsOn: DeployStaging
jobs:
- deployment: DeployToProduction
environment: production
strategy:
runOnce:
preDeploy:
- script: strata deploy run -f deployments/deploy-prd.yaml --dry-run
deploy:
- script: strata repo sync
- script: strata deploy run -f deployments/deploy-prd.yaml --force
Detecting version updates
Monitor if production is behind the latest release:
# In CI/CD (e.g., daily check):
strata repo status --output json | \
jq '.repos[] | select(.name == "infra") | .tags.latest_release'
If the current production pin is older than the latest release tag, you have an update available.
Handling Repository Changes
Adding a new file to a repository
Add the file to the git repo:
cd .strata/repos/infra git add terraform/new-module.tf git commit -m "Add new module" git push
Reference it in your deployment config:
# deployments/deploy-prd.yaml spec: provisioners: - name: terraform source: repository: infra source_path: terraform # now includes new-module.tf
Sync and deploy:
strata repo sync strata deploy run -f deployments/deploy-prd.yaml --force
Updating a repository (switching branch or tag)
Change the version in your environment config:
# environments/env-prd.yaml
spec:
repositories:
- name: infra
version: v2.3.0 → v2.4.0 # update to newer release
Then:
strata repo sync
strata deploy run -f deployments/deploy-prd.yaml --force
strata will check out the new version and regenerate artifacts.
Rolling back to a previous repository version
Revert the version pin in your environment config:
# Revert: v2.4.0 → v2.3.0
repositories:
- name: infra
version: v2.3.0
Then:
strata repo sync
strata deploy run -f deployments/deploy-prd.yaml --force
Terraform will detect the change and roll back the infrastructure.
Multi-Repo Workflows
Workflow 2: Monorepo split across multiple working directories
Your team has a monorepo but wants to work with subdirectories as separate repos locally:
Repository structure:
xyz-monorepo/
- terraform/
- ansible/
- helm/
Setup (on each developer machine):
cd xyz-deployments
strata sln init my-platform
# Register local subdirectories as separate repos
strata repo add terraform /path/to/xyz-monorepo/terraform --type local
strata repo add ansible /path/to/xyz-monorepo/ansible --type local
strata repo add helm /path/to/xyz-monorepo/helm --type local
Reference them:
spec:
provisioners:
- name: terraform
source:
repository: terraform
source_path: . # root of terraform/ subdir
- name: ansible
source:
repository: ansible
source_path: playbooks
Workflow 3: Enterprise setup with central module registry
Repository structure:
org/xyz-terraform-modules (public or private)
- modules/
- vpc/
- compute/
- database/
team-a/xyz-deployments
- deployments/
- deploy-a-prd.yaml
team-b/xyz-deployments
- deployments/
- deploy-b-prd.yaml
Team A setup:
cd team-a/xyz-deployments
strata repo add org-modules https://github.com/org/xyz-terraform-modules.git --clone
Team B setup:
cd team-b/xyz-deployments
strata repo add org-modules https://github.com/org/xyz-terraform-modules.git --clone
Both teams use the same central module registry, but each team’s deployment is independent.
Troubleshooting
“Repository not found” error
Error: Repository 'infra' not registered
Check:
strata repo list
Register it if missing:
strata repo add infra https://github.com/org/xyz-infrastructure.git --clone
“Reference not resolved” error
Error: @infra/terraform/main.tf not found
Check:
The file actually exists in the repo:
ls -la .strata/repos/infra/terraform/main.tf
The repository is synced to the correct version:
cd .strata/repos/infra && git log -1
The path in your YAML is correct (relative to the repo root, not to source_path)
Repository is dirty (uncommitted changes)
If a repository has uncommitted changes and you run strata repo sync --force, it will hard-reset:
cd .strata/repos/infra
git status # see uncommitted changes
# Option 1: Stash changes locally
git stash
# Option 2: Let strata hard-reset
strata repo sync --name infra --force
Slow sync (large repositories)
If syncing takes too long:
Use shallow clones (repo registration):
git clone --depth 1 <url>
Currently not exposed in strata CLI, but you can pre-clone manually and register as local.
Use a GitHub personal token (faster auth):
git config credential.helper store echo "https://user:token@github.com" > ~/.git-credentials strata repo sync
Best Practices
Register repos once per workspace — they’re shared across all deployments
Use semantic versioning —
vX.Y.Ztags for releasesPin production to release tags — never use branches (too unstable)
Pin staging to quality-gate tags — use tags like
testedorapproved-for-stagingUse branches for development —
developorfeature/*for dev environmentsTag after CI passes — automatic step in your CI/CD pipeline
Document the version matrix — keep a table of which env uses which repo version
Review repo diffs before deploying —
strata repo statusshows what changedTest promotion locally first — use
--dry-runto verify before promoting to higher envsAudit repository changes — integrate
strata repo statusinto your compliance dashboard
See Also
Environment Composition — layering configs
Commands Reference — repo — full command documentation
Multi-repo setup decision — design rationale