Skip to content

Prepare the Repositories

The platform uses two kinds of repository (Repo setup): the code repository, which is the same for every customer, and one configuration repository per customer. This page describes how to set them up in the customer's Azure DevOps project or GitHub organization, how the code arrives there, and which protections to switch on and when.

What you create

Repository Name (example) Content at the start Written by
Code xms-cloud-platform-code A copy of the released code, synced in. Read-only for the customer's team. The sync only
Configuration xms-cloud-platform-config A copy of the template configuration (environments/canary, environments/prod, pipelines/, .github/workflows/) The platform team

Spoke files are part of the configuration repository (<env-folder>/spokes/). The spoke canvas Terraform is part of the code repository. Older versions used four repositories; see Older layouts.

Where the repositories live

  • Azure DevOps: a private project in the customer's organization, with Git repositories.
  • GitHub: repositories in the customer's organization, with default settings.
  • In the managed model, the code repository is also kept on the provider's own host and synced to the customer. In the self-managed model you sync a release from the provider's published source into your own host and decide when to update it (Versioning).

1. Create the repositories

Azure DevOps

  1. Open the project, Repos, New repository. Type Git. Name: the code repository name. Repeat for the configuration repository.
  2. Clone the configuration repository. If it has no main branch yet, create one with an empty commit, and work on a separate branch for the implementation:

    git checkout --orphan main
    git commit --allow-empty -m "Initial empty commit"
    git push -u origin main
    git checkout -b initial
    

GitHub

  1. Create both repositories with default settings.
  2. In the code repository, open Settings, Actions, General, Access and allow access from repositories in the organization, so that the configuration repository can use its workflows.
  3. In the configuration repository, create main with an empty commit and an initial branch as above. Set the default branch to initial while you implement, and back to main when the implementation is done.

2. Bring the code in

The code repository is not edited in the customer's host. It receives released versions (branches release/vX.Y and tags vX.Y.Z) from the provider's source. How that works depends on the operating model:

  • Managed model. XMMS runs a sync from its own code repository. You give the sync a way to write to the customer repository (see below) and XMMS adds the customer repository as a target.
  • Self-managed model. You obtain the release from the provider and push it to the code repository yourself, or set up an equivalent sync. Agree the delivery mechanism with the provider.

Whichever mechanism you use, the result must be: the code repository on the customer's host contains the release branches and tags that the configuration repository pins, and nobody else changes it.

Target on GitHub: a GitHub App for the sync

The sync authenticates as a GitHub App installed in the customer's organization. Creating and managing it needs the App Manager role.

  1. Organization settings, Developer settings, GitHub Apps, New GitHub App.
  2. Name and description that say what it does (for example "repository sync"). Webhook: inactive.
  3. Repository permissions: Contents: read and write, Workflows: read and write.
  4. Where can it be installed: only on this account.
  5. After creation, note the App ID and generate a private key (.pem). Store the key in the secret store of the party that runs the sync, and hand over the App ID.
  6. Install the app, choose Only select repositories, and select the code repository (and, in older layouts, the spoke code repository). Note the installation ID.

The sync signs a token request with the key and exchanges it for a short-lived installation token.

Lock the target repository

Make the code repository read-only for everyone except the sync, with a ruleset on all branches that blocks creating, updating and deleting refs and non-fast-forward pushes, and lets the app bypass it.

# Requires the GitHub CLI (gh auth login) and PowerShell 7. Run once per code repository.
$sync_app_id = "<app-id>"
$org         = "<organization>"
$repo        = "xms-cloud-platform-code"
$body = @"
{
  "name": "RO-enforcement",
  "target": "branch",
  "enforcement": "active",
  "conditions": { "ref_name": { "include": ["~ALL"], "exclude": [] } },
  "rules": [
    {"type": "deletion"},
    {"type": "non_fast_forward"},
    {"type": "creation"},
    {"type": "update"}
  ],
  "bypass_actors": [
    { "actor_id": $sync_app_id, "actor_type": "Integration", "bypass_mode": "always" }
  ]
}
"@
$body | gh api --method POST "/repos/$org/$repo/rulesets" --input -

Test the sync after you lock the repository

Run a sync after you create the ruleset and check that the app can still write. A ruleset that blocks the sync is the usual cause of a failed first sync.

Target on Azure DevOps

The entry pipelines reference the code repository as a repository resource (mcp-code). Depending on the setup, that resource points to the provider's host through a service connection (the endpoint: in the entry file, see Versioning), or to a synced copy in the customer's own project. In the second case, agree in the plan phase which identity writes to the code repository, give only that identity write access, and block all other writers with a branch policy.

3. Fill the configuration repository

  1. Copy the template into the configuration repository on the initial branch. The template is the Demo configuration in the code repository (config/Demo/), or a template repository that your provider gives you.
  2. Adapt it with the mapping. Remove content that does not apply (other customers' spokes, sample policies you do not want).
  3. In every entry pipeline (pipelines/*.yaml or .github/workflows/*.yaml), set the code repository reference and the pinned version (Versioning), the agent pool, the service connections and the environments.
  4. Commit and push to initial.

Keep the work on initial until the platform is validated. That way main always describes a configuration that was deployed and checked, and the branch protections below do not slow down the implementation.

4. Protect the repositories at the end of the implementation

Switch these on after the validation, before the hand-over. Use a group of reviewers that the customer agrees to (example name: <platform approvers group>).

Protection Azure DevOps GitHub
Approval before prod runs Environment prod (and a spoke environment such as <spoke environment>-prod) with approvers; project administrators have the Administrator role on it; approvers may not approve their own runs Environment prod with required reviewers (the approver group), Prevent self-review on, Allow administrators to bypass off. Also the environment approval-required for the Approve* modes (Pipelines).
Review before merge to main A cross-repository branch policy on the default branch: automatically included reviewers = the approver group, required, minimum 1 reviewer, requestors may not approve their own changes A ruleset on main: require a pull request with 1 approval, approval of the most recent reviewable push, conversation resolution, squash merge only, block force pushes
Spoke files verified before merge Build validation on the configuration repository: the spoke verification pipeline, automatic trigger, required, build expiration 12 hours A pull request workflow that runs the config tests
Read access for approvers The approver group can read the repositories The approver group has read access to the repositories

Finally open a pull request from initial to main and merge it. In GitHub, set the default branch back to main and update the federated credential for the branch (see GitHub variant).

Older layouts

Older layout Replaced by Notes
Four repositories: platform code, platform config, spoke canvas code, spoke canvas config Two repositories (code and configuration) in the current layout In the older layout the spoke files live in spokes/tfspokes/<workload>/ of the spoke configuration repository, and the spoke deployment uses its own pipeline and state container.
A separate repository for the self-hosted agents (Terraform and an image build) The infrastructure and container pipelines in the code repository See Pipelines and agents.
One repository per customer with all code and parameters (mono-repo), or a single landingzone.yml pipeline Layered deployment See Migrating from an older platform version.

For the spoke canvas as a separate deployment (own code repository and pipeline), see Prepare the spoke pipeline: the code either stays with the platform team and is read through a service connection, or is copied into the customer's organization.

Check which layout your pinned version expects: the entry pipelines and the release notes of the version tell you.