Skip to content

docs: Advanced Topic — monorepo support and multi-product builds #803

@frostebite

Description

@frostebite

Summary

Add an advanced topics documentation page covering Orchestrator's monorepo support — how to build multiple products from a single repository using submodule profiles, variant overlays, selective initialization, and per-product CI workflows.

Motivation

Monorepo Unity projects (multiple games/products sharing a common engine/framework in one repository) are increasingly common in studios. They offer code sharing, consistent tooling, and simplified dependency management — but they make CI significantly harder:

  • Each product needs different submodules initialized
  • Build methods, scenes, and addressables differ per product
  • CI matrix explodes: products × platforms × build types
  • Cache isolation is critical — one product's Library folder is useless for another
  • LFS pull should only fetch assets relevant to the current product

Orchestrator's submodule profile system was specifically designed for this use case. This documentation page shows how to combine profiles, variants, cache keys, and matrix builds into a cohesive monorepo CI strategy.

Proposed Content

Submodule Profile Architecture

How profiles control which submodules are active per product:

# config/submodule-profiles/game-a/default/profile.yml
primary_submodule: Assets/_Game/Submodules/GameA
submodules:
  - name: Assets/_Engine/Core
    branch: main          # always needed
  - name: Assets/_Game/Submodules/GameA
    branch: main          # this product
  - name: Assets/_Game/Submodules/GameB
    branch: empty         # skip — different product
  - name: Assets/_Engine/Submodules/Plugins*
    branch: main          # glob pattern — all plugins

Variant Overlays

How variants modify base profiles for different build configurations:

# config/submodule-profiles/game-a/server/server.yml
# Overlays on top of default/profile.yml
submodules:
  - name: Assets/_Engine/Submodules/NetworkServer
    branch: main         # server-only submodule
  - name: Assets/_Game/Submodules/GameA
    branch: server       # server branch of the game

Matrix Build Strategy

Setting up CI to build multiple products from one repo:

strategy:
  matrix:
    product: [game-a, game-b, shell]
    platform: [StandaloneLinux64, StandaloneWindows64]

steps:
  - uses: game-ci/unity-builder@v4
    with:
      targetPlatform: ${{ matrix.platform }}
      submoduleProfilePath: config/submodule-profiles/${{ matrix.product }}/default/profile.yml
      cacheKey: ${{ matrix.product }}-${{ matrix.platform }}-${{ github.ref_name }}
      buildMethod: ${{ matrix.product == 'game-a' && 'GameA.Build.Run' || 'GameB.Build.Run' }}

Cache Isolation by Product

Why each product needs its own cache key and how to structure it:

  • Library folders are product-specific (different imported assets)
  • LFS objects may overlap but should be cached independently
  • Build artifacts go to product-specific output paths
  • Cache inheritance: shared engine cache reusable across products

Framework Configuration Files

How to define product metadata (build methods, Steam IDs, platform support) in YAML:

# config/frameworks.yml
frameworks:
  game-a:
    build_method: GameA.Pipeline.Build
    steam_app_id: 12345
    platforms: [StandaloneLinux64, StandaloneWindows64, StandaloneOSX]
    
  game-b:
    build_method: GameB.Pipeline.Build
    steam_app_id: 67890
    platforms: [StandaloneLinux64, Android, iOS]

Selective Testing

Using test suite profiles per product:

# .game-ci/test-suites/game-a-pr.yml
name: game-a-pull-request
runs:
  - name: unit-tests
    editMode: true
    filters:
      Domain: GameA
      Scope: Unit,Integration

Directory Structure Conventions

Recommended layout for monorepo Unity projects:

MonoRepo/
├── Assets/
│   ├── _Engine/              # Shared engine code
│   │   └── Submodules/       # Engine submodules
│   └── _Game/
│       ├── Shared/           # Shared game code
│       └── Submodules/       # Product submodules
│           ├── GameA/
│           └── GameB/
├── config/
│   ├── frameworks.yml        # Product definitions
│   └── submodule-profiles/   # Per-product profiles
│       ├── game-a/
│       │   ├── default/profile.yml
│       │   └── server/server.yml
│       └── game-b/
│           └── default/profile.yml
└── .github/
    └── workflows/
        └── build-matrix.yml  # Matrix build across products

Documentation Location

docs/03-github-orchestrator/07-advanced-topics/16-monorepo-support.mdx

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationorchestratorOrchestrator module

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions