Uc005 Init Mono Repo
# specs/domain/features/UC005-init_mono_repo.feature
#
# SINGLE SOURCE OF TRUTH for mono-repo initialization behaviour.
# This file is:
# (1) referenced by specs/domain/use_cases/UC005-init_mono_repo.md (documentation)
# (2) executed by the acceptance test suite (living documentation)
#
# Rules:
# - Scenario IDs (e.g. UC005-S01) must match the use case document.
# - Step definitions live in: internal/acceptance/
# - Keep scenarios focused: one behaviour per scenario.
# - Use exact terms from specs/domain/glossary.md.
# - Per-combination happy-path coverage of a single artifact's generated files already lives
# in UC001-*.feature; this file only covers the multi-artifact orchestration on top of it.
Feature: Initialize a Mono-Repo With Multiple Artifacts
As a software engineer
I want to describe several related artifacts in one .mono-repo.yaml manifest
So that I can generate all of them into one Git repository with a single `repo init` call.
# ---------------------------------------------------------------------------
# Happy path: manifest with multiple entries → one subdirectory per entry
# ---------------------------------------------------------------------------
Scenario: UC005-S01 Successful initialization of a mono-repo with two artifacts
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| copyrightStatement | (c) 2026 Holger Zahnleiter |
| ci | gitlab |
And its repos list contains:
| Name | Authors | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | Holger Zahnleiter | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Trip Booking Frontend | John Doe | typescript | frontend-react | Trip Booking Web-Frontend | trip-booking-frontend | |
When the user runs "repo init" without CLI arguments
Then the init command exits with a zero exit code
And the repository contains a subdirectory flight-booking
And the repository contains a subdirectory trip-booking-frontend
And flight-booking/.repo.yaml contains:
| Field | Value |
| language | java |
| type | service |
| ci | gitlab |
| name | Flight Booking |
And trip-booking-frontend/.repo.yaml contains:
| Field | Value |
| language | typescript |
| type | frontend-react |
| ci | gitlab |
| name | Trip Booking Frontend |
# ---------------------------------------------------------------------------
# Error: an entry's target subdirectory already exists
# ---------------------------------------------------------------------------
Scenario: UC005-S02 Init fails when an entry's target subdirectory already exists
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
And a subdirectory flight-booking already exists
When the user runs "repo init" without CLI arguments
Then the init command exits with a non-zero exit code
And the init command reports an error containing "flight-booking"
And no new generated files are written to disk
# ---------------------------------------------------------------------------
# Error: duplicate artifact names within one manifest
# ---------------------------------------------------------------------------
Scenario: UC005-S03 Init fails when two entries share the same artifact name
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Flight Booking 2 | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
When the user runs "repo init" without CLI arguments
Then the init command exits with a non-zero exit code
And the init command reports an error containing "duplicate"
And no generated files are written to disk
# ---------------------------------------------------------------------------
# Error: an entry has an invalid language/type combination
# ---------------------------------------------------------------------------
Scenario: UC005-S04 Init fails when an entry has an invalid language/type combination
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name |
| Flight Booking | go | embedded | Flight Booking Service | flight-booking |
When the user runs "repo init" without CLI arguments
Then the init command exits with a non-zero exit code
And the init command reports an error containing "flight-booking"
And no generated files are written to disk
# ---------------------------------------------------------------------------
# CI composition: root pipeline gates each entry by its own subdirectory
# ---------------------------------------------------------------------------
Scenario: UC005-S06 Root GitLab CI triggers each entry only on its own subdirectory's changes
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Trip Booking Frontend | typescript | frontend-react | Trip Booking Web-Frontend | trip-booking-frontend | |
When the user runs "repo init" without CLI arguments
Then the root .gitlab-ci.yml contains a trigger job for flight-booking gated by a changes rule on flight-booking/**
And the root .gitlab-ci.yml contains a trigger job for trip-booking-frontend gated by a changes rule on trip-booking-frontend/**
And flight-booking/.gitlab-ci.yml has the same jobs as a standalone java service would generate, except the docs (Pages) job is omitted
# A `changes:` rule always evaluates to true in a tag pipeline, so without an explicit tag
# gate every artifact's child pipeline would fire on any artifact's tag, and all but one
# would fail with "no jobs" (ADR-016).
Scenario: UC005-S10 Root GitLab CI triggers only the tagged artifact's child pipeline
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Trip Booking Frontend | typescript | frontend-react | Trip Booking Web-Frontend | trip-booking-frontend | |
When the user runs "repo init" without CLI arguments
Then the root .gitlab-ci.yml job trigger-flight-booking is gated on tag pattern ^flight-booking-v
And the root .gitlab-ci.yml job trigger-trip-booking-frontend is gated on tag pattern ^trip-booking-frontend-v
# ---------------------------------------------------------------------------
# Root specs: system-wide content gets its own root-level home (ADR-013)
# ---------------------------------------------------------------------------
Scenario: UC005-S07 Root specs skeleton is scaffolded for system-wide content
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
When the user runs "repo init" without CLI arguments
Then the repository contains a file specs/architecture/ADRs/README.md
And the repository contains a file specs/domain/business_rules.md
And the repository contains a file specs/index.md
# ---------------------------------------------------------------------------
# Error: manifest with an empty repos list
# ---------------------------------------------------------------------------
Scenario: UC005-S05 Init fails when the manifest's repos list is empty
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list is empty
When the user runs "repo init" without CLI arguments
Then the init command exits with a non-zero exit code
And the init command reports an error containing "repo entry"
# ---------------------------------------------------------------------------
# Docs aggregation: root mkdocs.yml combines every entry's own docs (ADR-015)
# ---------------------------------------------------------------------------
Scenario: UC005-S09 Root mkdocs.yml combines every entry's own documentation
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Trip Booking Frontend | typescript | frontend-react | Trip Booking Web-Frontend | trip-booking-frontend | |
When the user runs "repo init" without CLI arguments
Then the repository contains a file mkdocs.yml
And the root mkdocs.yml includes flight-booking/mkdocs.yml
And the root mkdocs.yml includes trip-booking-frontend/mkdocs.yml
And the root .gitlab-ci.yml contains a pages job that does not depend on any trigger job
# GitLab deploys any job named exactly `pages`, so proving the site still builds without
# publishing it needs a second, differently-named job (ADR-016).
Scenario: UC005-S11 Combined docs site is built on every change but published only on a release tag
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Trip Booking Frontend | typescript | frontend-react | Trip Booking Web-Frontend | trip-booking-frontend | |
When the user runs "repo init" without CLI arguments
Then the root .gitlab-ci.yml job docs-build is not gated on any tag
And the root .gitlab-ci.yml job pages is gated on tag pattern flight-booking|trip-booking-frontend
And the root specs/index.md has a released-version table row for flight-booking
And the root specs/index.md has a released-version table row for trip-booking-frontend
# ---------------------------------------------------------------------------
# Real-backend E2E orchestration: root docker-compose files + e2e CI stage
# ---------------------------------------------------------------------------
Scenario: UC005-S12 Root docker-compose files orchestrate every service/frontend-react entry
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Flight Booking | java | service | Flight Booking Service | flight-booking | example.org/acme/flight-booking |
| Trip Booking Frontend | typescript | frontend-react | Trip Booking Web-Frontend | trip-booking-frontend | |
When the user runs "repo init" without CLI arguments
Then the repository contains a file docker-compose.yml
And the repository contains a file docker-compose.e2e.yml
And docker-compose.yml builds flight-booking from ./flight-booking on port 8080
And docker-compose.e2e.yml pulls flight-booking's :latest image on port 8080
And the root .gitlab-ci.yml contains an e2e-test-real-backend job in stage e2e
Scenario: UC005-S13 No docker-compose files are generated when no entry has a runtime container
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name | Module |
| Shared Lib | go | library | Shared library | shared-lib | example.org/acme/shared-lib |
When the user runs "repo init" without CLI arguments
Then the repository does not contain a file docker-compose.yml
And the root .gitlab-ci.yml does not contain an e2e-test-real-backend job
Scenario: UC005-S08 Init fails when a Java entry has no module path
Given current directory is an empty Git repository containing a .mono-repo.yaml with:
| Field | Value |
| name | Demo App |
| ci | gitlab |
And its repos list contains:
| Name | Language | Type | Description Brief | Artifact Name |
| Flight Booking | java | service | Flight Booking Service | flight-booking |
When the user runs "repo init" without CLI arguments
Then the init command exits with a non-zero exit code
And the init command reports an error containing "flight-booking"
And the init command reports an error containing "artifact.module"
And no generated files are written to disk