Recipes and Patterns

Practical examples for common use cases.

Standard Project Setups

Rust CLI Project

A complete Rust CLI project with CI, pre-commit hooks, and conventional commits.

# .common-repo.yaml

# Inherit base Rust CLI configuration
- repo:
    url: https://github.com/common-repo/rust-cli
    ref: v2.0.0
    with:
      - include: ["**/*"]
      - exclude: [".git/**", "target/**", "src/**"]

# Add pre-commit hooks for Rust
- repo:
    url: https://github.com/common-repo/pre-commit-rust
    ref: v1.0.0
    with:
      - include: [".pre-commit-config.yaml"]

# Project-specific variables
- template-vars:
    project_name: my-cli
    author: Your Name
    description: A command-line tool

# Mark config files as templates
- template:
    - Cargo.toml
    - README.md
    - .github/workflows/*.yml

# Require essential tools
- tools:
    - rustc: ">=1.70"
    - cargo: "*"
    - pre-commit: ">=3.0"

Python Project with UV

Modern Python project using UV for dependency management.

# .common-repo.yaml

# Base Python project structure
- repo:
    url: https://github.com/common-repo/python-uv
    ref: v1.0.0
    with:
      - include: ["**/*"]
      - exclude: [".git/**", "__pycache__/**", ".venv/**"]

# Pre-commit hooks for Python
- repo:
    url: https://github.com/common-repo/pre-commit-python
    ref: v1.5.0
    with:
      - include: [".pre-commit-config.yaml"]

# Variables
- template-vars:
    project_name: my-python-project
    python_version: "3.11"
    author: Your Name

- template:
    - pyproject.toml
    - README.md

- tools:
    - python: ">=3.11"
    - uv: "*"

Node.js/TypeScript Project

TypeScript project with ESLint, Prettier, and GitHub Actions.

# .common-repo.yaml

# TypeScript base configuration
- repo:
    url: https://github.com/common-repo/typescript
    ref: v3.0.0
    with:
      - include:
          - tsconfig.json
          - .eslintrc.json
          - .prettierrc
          - .github/**

# Add package.json dependencies
- json:
    source: dev-deps.json
    dest: package.json
    path: devDependencies

- template-vars:
    project_name: my-project
    node_version: "20"

- tools:
    - node: ">=20"
    - npm: ">=10"

Upstream Repo Patterns

Upstream Repo That Consumes Its Own Tooling

An upstream repo that provides shared configuration to consumers, while also pulling CI and release tooling for its own use. The self: block keeps local consumption separate from the source API.

# .common-repo.yaml in an upstream repo

# Pull tooling for this repo only — consumers never see this
- self:
    - repo:
        url: https://github.com/org/release-tooling
        ref: v3.0.0
    - repo:
        url: https://github.com/org/ci-base
        ref: v1.2.0
    - exclude:
        - ".releaserc.yaml"
        - "commitlint.config.cjs"

# Source API — what consumers inherit
- include:
    - "configs/**"
    - ".github/**"
- template:
    - ".github/workflows/ci.yml"
- template-vars:
    GH_APP_ID_VAR: ORG_APP_ID
- rename:
    - from: "^configs/(.*)$"
      to: "$1"

Without self:, the release tooling and CI base files would leak into every consumer that inherits from this repo. See Authoring Upstream Repositories for more details.

CI/CD Patterns

GitHub Actions Workflow Inheritance

Inherit and customize GitHub Actions workflows.

# .common-repo.yaml

# Base CI workflows
- repo:
    url: https://github.com/your-org/ci-templates
    ref: v2.0.0
    with:
      - include: [".github/**"]

# Add project-specific jobs to CI
- yaml:
    source: local-ci-jobs.yml
    dest: .github/workflows/ci.yml
    path: jobs
    append: true

# Customize workflow variables
- template-vars:
    default_branch: main
    node_version: "20"
    deploy_environment: production

- template:
    - ".github/workflows/*.yml"

local-ci-jobs.yml:

integration-tests:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - name: Run integration tests
      run: ./scripts/integration-test.sh

Multi-Stage Deployment

Different configurations for different environments.

# .common-repo.yaml

# Base deployment configuration
- repo:
    url: https://github.com/your-org/deploy-configs
    ref: v1.0.0
    path: kubernetes  # Only kubernetes configs

# Environment-specific overrides
- yaml:
    source: env/production.yml
    dest: kubernetes/deployment.yml
    path: spec.template.spec

- template-vars:
    environment: staging
    replicas: "3"
    image_tag: latest

- template:
    - "kubernetes/*.yml"

Organization Standards

Company-Wide Defaults

Create a base configuration that all projects inherit.

In your org’s base repo (github.com/your-org/base-config):

# .common-repo.yaml (this repo exports these files)

- include:
    - .editorconfig
    - .gitignore
    - .github/CODEOWNERS
    - .github/PULL_REQUEST_TEMPLATE.md
    - .github/ISSUE_TEMPLATE/**
    - LICENSE

- template-vars:
    org_name: Your Organization
    support_email: support@your-org.com

In each project:

# .common-repo.yaml

# Inherit org-wide defaults
- repo:
    url: https://github.com/your-org/base-config
    ref: v1.0.0

# Add language-specific configuration
- repo:
    url: https://github.com/your-org/rust-standards
    ref: v2.0.0

# Project-specific customization
- template-vars:
    project_name: my-service
    team: platform

Security Configurations

Standardize security tooling across projects.

# .common-repo.yaml

# Security scanning configuration
- repo:
    url: https://github.com/your-org/security-configs
    ref: v1.2.0
    with:
      - include:
          - .github/workflows/security.yml
          - .snyk
          - .trivyignore

# Merge security checks into existing CI
- yaml:
    source: security-jobs.yml
    dest: .github/workflows/ci.yml
    path: jobs
    append: true

Monorepo Patterns

Shared Configuration Across Packages

Use path filtering to share configs in a monorepo.

# packages/web/.common-repo.yaml

# Inherit from monorepo root configs
- repo:
    url: https://github.com/your-org/your-monorepo
    ref: main
    path: shared/web-configs
    with:
      - include: ["**/*"]

# Package-specific settings
- template-vars:
    package_name: web
    port: "3000"

Multiple Config Repositories

Compose from multiple specialized config repos.

# .common-repo.yaml

# Linting standards
- repo:
    url: https://github.com/your-org/lint-configs
    ref: v2.0.0
    with:
      - include: [".eslintrc.json", ".prettierrc"]

# Testing configuration
- repo:
    url: https://github.com/your-org/test-configs
    ref: v1.5.0
    with:
      - include: ["jest.config.js", "vitest.config.ts"]

# CI/CD templates
- repo:
    url: https://github.com/your-org/ci-configs
    ref: v3.0.0
    with:
      - include: [".github/**"]

Configuration Merging

Extending package.json

Add dependencies without overwriting the whole file.

# .common-repo.yaml

# Base project
- repo:
    url: https://github.com/your-org/node-base
    ref: v1.0.0

# Add shared dev dependencies
- json:
    source: shared-dev-deps.json
    dest: package.json
    path: devDependencies

# Add shared scripts
- json:
    source: shared-scripts.json
    dest: package.json
    path: scripts
    append: true

shared-dev-deps.json:

{
  "eslint": "^8.0.0",
  "prettier": "^3.0.0",
  "typescript": "^5.0.0"
}

Merging Cargo.toml Dependencies

Add common Rust dependencies.

# .common-repo.yaml

- repo:
    url: https://github.com/your-org/rust-base
    ref: v1.0.0

# Add logging dependencies
- toml:
    source: logging-deps.toml
    dest: Cargo.toml
    path: dependencies

# Add dev dependencies
- toml:
    source: dev-deps.toml
    dest: Cargo.toml
    path: dev-dependencies

logging-deps.toml:

tracing = "0.1"
tracing-subscriber = "0.3"

Extending Pre-commit Hooks

Add hooks to an existing pre-commit configuration.

# .common-repo.yaml

# Base pre-commit config
- repo:
    url: https://github.com/your-org/pre-commit-base
    ref: v1.0.0
    with:
      - include: [".pre-commit-config.yaml"]

# Add additional hooks
- yaml:
    source: extra-hooks.yml
    dest: .pre-commit-config.yaml
    path: repos
    append: true

extra-hooks.yml:

- repo: local
  hooks:
    - id: custom-check
      name: Custom Check
      entry: ./scripts/check.sh
      language: script

Advanced Patterns

Conditional Configuration via Environment

Use environment variables for conditional behavior.

# .common-repo.yaml

- repo:
    url: https://github.com/your-org/base-config
    ref: v1.0.0

- template-vars:
    # Default to development settings
    log_level: debug
    enable_metrics: "false"

    # CI-specific overrides
    ci_mode: "false"

- template:
    - config/*.yml

Version Pinning Strategy

Pin specific versions while allowing updates.

# .common-repo.yaml

# Pin to specific major version for stability
- repo:
    url: https://github.com/your-org/stable-configs
    ref: v2.0.0  # Update manually for major versions

# Use branch for frequently updated configs
- repo:
    url: https://github.com/your-org/evolving-configs
    ref: main  # Always get latest (use with caution)

# Use commit SHA for maximum reproducibility
- repo:
    url: https://github.com/your-org/critical-configs
    ref: abc123def456  # Exact commit

Template File Patterns

Use template files for customization.

In config repo:

templates/
  Cargo.toml.template
  README.md.template

In .common-repo.yaml:

- repo:
    url: https://github.com/your-org/rust-templates
    ref: v1.0.0
    with:
      - include: ["templates/**"]
      - rename:
          - "templates/(.+)\\.template$": "$1"

- template-vars:
    project_name: my-project
    description: A great project
    license: MIT

- template:
    - Cargo.toml
    - README.md

Debugging Tips

Verbose Output

# See detailed processing (debug level)
common-repo apply --verbose

# Maximum verbosity (trace level)
common-repo apply --verbose --verbose

Inspect Before Applying

# List what would be created
common-repo ls -l

# See the diff
common-repo diff

# Dry run
common-repo apply --dry-run

Check Inheritance

# View inheritance tree
common-repo tree

# Get configuration overview
common-repo info

Validate Configuration

# Check syntax
common-repo validate

# Also check repo accessibility
common-repo validate --check-repos