Skip to content

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