# 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