Skip to content

Latest commit

 

History

34 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scaffold-repo

Managing one repository is easy. Managing twenty interconnected micro-repos—keeping their build scripts, OSS licenses, CI pipelines, and Git workflows synchronized across multiple languages—is a nightmare.

scaffold-repo is a Declarative Fleet Manager and build orchestrator for polyglot ecosystems. Instead of manually updating 20 different CMakeLists.txt or pyproject.toml files, you define your company's standards in a centralized Template Registry. With a single CLI command, scaffold-repo resolves dependency graphs, injects stack-specific build scripts, enforces license compliance, and orchestrates Git branching across your entire fleet.


📦 Installation

Since scaffold-repo is a global fleet manager, it is highly recommended to install it using pipx so it is isolated but globally available on your command line.

# 1. Clone the orchestrator
git clone https://github.com/contactandyc/scaffold-repo.git
cd scaffold-repo

# 2. Install globally
pipx install .

# (Optional) If you are actively developing the templates or engine:
pip install -e .

Verify the installation by running: scaffold-repo --help


⏱️ The 10-Second Overview

1. Initialize your Workspace:

scaffold-repo --init

The dynamic wizard connects to your company's Template Registry, asks you for your default development environments (like your preferred Python version or CMake generator), and drops a .scaffoldrc.yaml into your workspace.

2. Create a Project:

scaffold-repo --create my-python-app

Examples that use scaffold-repo

The engine asks what stack you want (e.g., Python, C++), applies your organizational profile, generates the initial code, and locks the configuration into a local scaffold.yaml.

3. Build and Develop predictably:

cd my-python-app
./build.sh install

The generated build.sh provides a predictable, standardized contract for developers. However, the repository is 100% standalone. You can bypass the script entirely and run standard cmake, make, pip, or python commands directly. scaffold-repo is never required to build or run the generated code.


🚀 Core Features

  • Zero Vendor Lock-In: Repositories generated by scaffold-repo are completely standalone units. They do not depend on the orchestrator to build, test, or run. The generated ./build.sh is simply a convenience wrapper to provide a unified interface across the fleet.
  • Fleet-Wide Aliases & Multi-Repo Execution: Define groups of repositories in resources/aliases.yaml. Run scaffold-repo my-team-alias --update to seamlessly clone, scaffold, and upgrade dozens of repositories concurrently.
  • The Ultimate Dry-Run (--diff): When managing a massive fleet, blindly applying template updates is dangerous. Run scaffold-repo all --diff to get a unified, bird's-eye view of exactly how your templates have drifted, what licenses need updating, or what local files are dirty across your entire ecosystem before modifying a single file on disk.
  • ✨ Context-Aware Execution: Once you cd into a generated project, scaffold-repo automatically detects your scaffold.yaml.
  • Decentralized, Git-Native Resolution: Dependencies aren't locked in a proprietary package manager. The engine reads YAML depends_on arrays that point to actual Git URLs, topologically sorts the graph, and automatically clones and builds external dependencies in the exact required order.
  • Automated OSS Compliance: Automatically translates and injects SPDX license headers into your code (// for C++, # for Python). Supports multi-license repositories natively—apply Apache-2.0 to your core project, but seamlessly enforce BSD-3 headers for files inside src/third_party/.

🧬 The Local Manifest & Separation of Concerns

A core philosophy of scaffold-repo is the strict separation of Implementation (the code) and Standardization (the templates).

While the global Template Registry dictates the rules of your ecosystem, the local scaffold.yaml file (sitting at the root of every generated repository) provides the context. This ensures that individual repositories maintain their own specific information and are never blindly tied to the orchestrator.

Furthermore, the depends_on array utilizes a Decentralized Graph. Notice that dependencies explicitly declare remote Git URLs or system packages, rather than relying on a proprietary internal registry:

Example scaffold.yaml:

project_title: A Map Reduce Library
version: 0.0.3
stack: c/cmake
date_created: 2025-08-01
# pulls profile from templates/profiles/default.yaml
profile: default

# 1. Bind to the centralized Template Registry
base_templates:
  repo: https://github.com/contactandyc/scaffold-templates.git
  ref: main

# 2. Decentralized, Git-native dependency linking
depends_on:
  - https://github.com/contactandyc/the-io-library.git
  - system/OpenSSL

# 3. Define inline, custom licenses for specific third-party files
licenses:
  lz4_custom:
    spdx: |
      SPDX-License-Identifier: BSD-2-Clause
      Portions © 2011–present Yann Collet
license_overrides:
  "src/third_party/lz4/**": lz4_custom

# 4. Route sub-applications and examples dynamically
apps:
  context:
    dest: examples
    depends_on:
      - https://github.com/contactandyc/a-map-reduce-library.git
  01_word_count:
    binaries:
      word_count:
        - src/main.c

Because the repository retains its own source of truth, it remains a standard, portable Git repository. The orchestrator merely reads this manifest to compute linking requirements, auto-discover source/test files, inject custom inline licenses to specific files, and execute the build graph.


🛠 The GitOps Workflow

scaffold-repo actively manages your development lifecycle, enforcing a clean main -> dev-* -> feat/* branching topology.

Note: The examples below show running commands inside a single repository. You can run these exact same commands against dozens of repositories at once from your workspace root by providing an alias: scaffold-repo my-alias --update

Workflow A: Developing a New Feature

1. Start a Feature

scaffold-repo --start-feature "add-auth"

Automatically checks out the current integration branch (e.g., dev-v0.1.1) and creates the branch feat/add-auth.

2. Compile & Iterate

scaffold-repo --build-deps --build

3. Commit and Push

scaffold-repo --commit "feat: added auth module" --push

Commits changes to your feature branch and pushes to origin. (The engine blocks direct commits to main or dev-*).

Workflow B: Updating Fleet Scaffolding

When the platform team updates a license or modifies a global template, you can sync the changes across your repositories effortlessly.

1. Preview the Fleet Drift

scaffold-repo --diff

Safely inspect exactly what files the engine wants to update across your active projects.

2. Apply Template Updates

scaffold-repo --update

Pulls down the latest templates and merges them with your code. Magic: If you are currently sitting on a protected dev-* branch, the engine will automatically spawn a chore/update-scaffolding branch for you!

3. Publish to Integration

scaffold-repo --publish-feature --push

Magic: Because you are on the chore/update-scaffolding branch, the engine automatically detects the dirty tree, commits the changes for you, merges the code into the dev-* integration branch, and cleans up the working branches!

Releasing

Once your features and updates are merged into the integration branch, cut the official release.

1. Release & Tag

scaffold-repo --publish-release --push

Checks out main, merges the dev branch, auto-tags the release based on your scaffold.yaml version, updates the registry, and pushes the tags to origin.


🏗 Under the Hood: The Template Registry

All of scaffold-repo's power comes from the Template Registry. The engine itself contains zero hardcoded opinions. By default, the engine connects to a central Base Registry that you dictate in your workspace configuration.

templates/
├── .scaffold-defaults.yaml    # Global router: defines global variables, prompts, and packages
├── base/                      # Universal repository defaults (e.g., .gitignore, AUTHORS)
├── stacks/                    # The technical implementations (e.g., c/cmake, python/standard)
├── profiles/                  # Organizational standards (author info, default licenses, tools)
├── mixins/                    # Modular, optional Jinja templates (changie, jekyll-site)
├── libraries/                 # The global dependency index (how to build/link external tools)
├── licenses/                  # SPDX logic and NOTICE file generators
├── app-resources/             # Special templates looped per sub-application inside a repo
└── resources/                 # Global assets like aliases.yaml or canonical license texts

If you are a Platform Engineer looking to write custom templates, configure organizational profiles, or define internal dependencies, please read the Template Authoring Guide.


💻 Complete CLI Reference

Usage: scaffold-repo [PROJECTS...] [OPTIONS]

Arguments:
  PROJECTS                  One or more projects/namespaces/aliases to scaffold or build.
                            (e.g., 'my-python-app', 'my-alias', 'all')
                            *Note: Omit if running inside a project directory!*

Workspace Options:
  --init                    Initialize a .scaffoldrc workspace configuration (Interactive)
  -C, --cwd PATH            Run as if started in <PATH> (default: current dir)
  --templates-dir PATH      Override templates directory (auto-detects ./templates)
  --start-feature NAME      Start a feature branch off the integration dev branch

Scaffolding Options:
  --create SLUG             Create a new project in the workspace (Interactive)
  --update                  Explicitly apply template updates to the targeted repositories
  --diff                    Print unpaginated Git diffs for targeted repos
  -y, --assume-yes          Apply template updates without prompting
  --show-diffs              Print inline diffs before applying file updates
  --no-prompt               Do not prompt during SPDX license header fixups

Dependency Lifecycle:
  --clone-deps              Fetch external dependencies without compiling
  --build-deps              Fetch, compile, and install external dependencies
  --clean-deps              Wipe build caches for dependencies

Target Lifecycle (Your Code):
  --clean                   Run './build.sh clean' on the targeted projects
  --build                   Run './build.sh build' on the targeted projects
  --install                 Run './build.sh install' on the targeted projects

Git Orchestration:
  --commit MSG              Commit changes (blocked on 'main' and 'dev-*')
  --publish-feature         Merge current feature branch into dev branch and delete feature
  --drop-feature            Discard current feature branch and uncommitted changes
  --publish-release         Merge dev branch into main, tag it, and update registry version
  --push                    Push commits to origin

About

A repo to scaffold other repos (handles licenses, builds, clones, makefiles, boilerplate stuff)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages