This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Release Train Manager

Aura Release Train Manager

Release Train Manager (RTM) implementation and architecture

Introduction to RTM development methodology

The “release train” software development methodology is a way of planning the delivery of software according to a predetermined and regular schedule, as if it were a “train timetable”. This schedule is public for all the teams that must contribute to the delivery and represents a commitment on their part, as the schedule must be adhered to.

If we use the metaphor: “the train will take the passengers who are ready to travel”, i.e., only the software that is ready to be integrated will be integrated. For this it is necessary to work on the different functionalities in parallel and in isolation without affecting the rest.

We start from a prioritized backlog. The tasks will enter the implementation phase in order of priority. 

RTM overview

The important thing when we are working on a new feature is to be able to completely isolate the development, environment and testing. To do this, environments will be generated per feature and git branches will be used for the different repositories involved.

RTM Overview

RTM Overview
  • INIT: initial processing of a feature (select repos involved, create branches on those repos and create environment).
  • TF (Tests Feature): daily smoke tests on feat/new-feature branches.
  • TFPR (Tests Feature PR): full regression tests on the master merge and the feat/new-feature branch.
  • TM (Tests Master): complete daily/weekly regression tests on the master branches.
  • PR Fx (PR Feature): PRs on the feat/new-feature branch.
  • PR Mx (PR Master): PRs on the master branch.

1 - Github as Orchestrator

Github as orchestrator

How to use a Github repository to orchestrate the Release Train Manager processes

Release Train Manager Repository

To organize the work, we use a Github repository. This repository contains classic branches for the RTM development cycle itself and a set of branches reserved for RTM orchestration. The default base branch of the orchestrator is master.

The classic branches contain the prefixes:

  • feat/description
  • fix/description
  • doc/description
  • etc.

The specific branches for the orchestrator contain a descriptive name and the JIRA identifier:

  • main/name_reference#id: To orchestrate new features.
  • release/name_reference#id: To orchestrate releases.
  • hotfix/name_reference#id: To orchestrate hotfix on a release.
  • fasttrack/name_reference#id: To orchestrate features on a release.

To manage the RTM processes, we use Pull Requests (PR) in this repository. Each of these PRs has a base branch and a target branch, depending on the operation to be performed:

- main       -> Base: master. Target: main/name_reference#id
- release    -> Base: master. Target: release/name_reference#id
- hotfix     -> Base: a release branch. Target: hotfix/name_reference#id
- fasttrack  -> Base: a release branch. Target: fasttrack/name_reference#id

This PR is generated automatically when a commit is made for the first time in one of these special branches.

Pull Request Body

In the body of the generated PR, all the configuration information for the branch is displayed and the Pull Request will contain all the history of processes executed on it in comment mode.

An example of PR body of a main branch

The information for the PR body is obtained from a configuration file and is updated as the different phases of the orchestrator are executed.

The Github Repository Structure

/
├─ .github/
│  ├─ PULL_REQUEST_TEMPLATE/
│  ├─ actions/
│  ├─ workflows/
├─ docs/
├─ resources/
│  ├─ templates/
├─ src/
│  ├─ tools/
│  │  ├─ build-docker/
│  │  ├─ build-actions/
│  ├─ toolkit/
│  │  ├─ nodejs/
│  │  │  ├─ package-manager/
│  │  │  │  ├─ operations/
├─ branch-config.yml

branch-config.yml

This file contains all the configuration associated with a special branch. In this file, the involved equipment, phases, steps, etc. are configured.

All the information is included in Branch Configuration section.

.github/actions

This folder contains Github Actions necessary to perform all operations on repositories, data persistence and communications with Jenkins, among others.

resource/templates

This folder contains templates for the branch-config.hml file for each branch type:

_main_      -> `main-branch-config.yml`
_hotfix_    -> `hotfix-branch-config.yml`
_release_   -> `release-branch-config.yml`
_fasttrack_ -> `fasttrack-branch-config.yml`

src/tools

It contains the tools needed to build the docker actions and images.

src/toolkit

It contains the code SDKs as a complement to the Github actions. These utilities will eventually become actions someday.

src/toolkit/nodejs

It contains the NodeJS toolkit. More information in [NodeJS Toolkit].
⚠️ NodeJS toolkit section WIP

.github/workflows

We define stage as a set of steps to be performed in a coordinated manner by each team. Until all the teams involved in the phase have completed all the steps of a phase, it will not be possible to move on to the next phase.

For example, for example, we can define the INIT phase in which the teams have to create the specific branches in their repositories and activate an environment where they can deploy. We would have that each team would have an INIT phase in its configuration, with a step to generate the branch or branches in its repositories, and the Devops team would also have another set of steps to prepare the environment.

All these configurations are explained in the Branch Configuration section.

In order to synchronize the work between the teams and perform these operations we will use Github Workflows. These workflows are explained in the [Workflows] section.
⚠️ Workflows section WIP

2 - Branch Configuration

Branch configuration

Description of the process for the configuration of branches in the Release Train Manager

Branch configuration file

The configuration of branches is defined in the branch-config.yml file.

Each stage defined in the schema is fully described in the Stages section.

Properties

Property type description default mandatory
name string Name of the branch. The format is: [main|hotfix|fasttrack|release]/description#jira-id
Example: name: main/doc-review#14820
none true
release_branch string Name of the base branch from which the specific branch is generated. master In hotfix and fasttrack branches
release_version string Version of the base branch from which the branch will be generated. none In release branches
environment string English letter name to indicate the environment number to be generated to deploy the components used in the special branch. none If an environment is needed: from one to ten
mode string It specifies whether the branch that has been generated is to make a “real” change to the repositories to perform a test. production Use developer for test purposes
version string Version of configuration file. 1.0.0 Not used yet
description string Brief description of the changes for which the branch has been generated. Fake text true
jira Jira Jira references and tags referring to the task that the branch solves. Fake data true
teams Map<string,Team> List of teams involved in the resolution of the task solved by this branch. none At least one
main_protection Object Protection that will be applied to main branch when created in the RTM repository. This configuration can be partial and will be merged with the default configuration.
All the documentation concerning the protection of a branch can be found at Github
Defined by Template true
protection Object Default configuration property, this configuration will be merged between custom protection configurations of teams or main branches.
All the documentation concerning the protection of a branch can be found at Github
Defined by Template true

Jira Property

Property type description default mandatory
tags string[] String words used in Jira to categorize the feature or bug. Fake data true
references string[] Jira URLs where the tasks that the branch solves once the life cycle is completed are Fake data true

Team Object

It contains a set of common properties and others customized by each team. In the following table, the properties that are shared by all teams are described.

Property type description default mandatory
repositories string[] List of repository names involved in the changes to be made to the branch. Defined by Template true
protection Object Security configuration of the branches to be generated in the repositories. This configuration can be partial and will be merged with the default configuration.
Example:
     protection:
restrictions:
users: []
teams:
- aura-ci
- aura-bot-global-dev
- aura-bot-ext-devs
apps: []

All the documentation concerning the protection of a branch can be found at Github
Defined by Template true
stages Map<string,string[]> Map of stages in which the team has a series of steps to perform. All steps that must be performed to complete the phase. Defined by Template true
tasks string[] List of custom tasks to be completed before closing the PR for the branch. These tasks will be converted into a checkbox component in the body of the Pull Request Fake data false

Team Bot Custom Properties

Description of the bot’s custom properties.

Property type description default mandatory
update_dependencies Object[] of {name: string, version: string} List of objects with name and version. This property is used to update dependencies on the modules in the repositories defined by aura-bot. All the modules that use one of the libraries in the list, will be updated to the version that has been specified. [] false
dependencies Object[] of {name: string, version: string} List of objects with name and version. This property contains those @telefonica libraries that are needed in the Github library repository to isolate dependencies. At the INIT stage, the system will pick up that library from NPM and publish it to Github. [] false
node_version number Version of node to use in the bot’s Workflows. 14 true
tools Object It currently contains only one property, POEditor, which specifies the creation of a separated project to manage the localization strings. Defined by Template false

Branch config File

name: master
environment: none
mode: production
version: 1.0.0
description: Text to describe the release changes
jira:
  tags:
    - MyTag
  references:
    - "https://jira.tid.es/browse/AURA-12941"
    - "https://jira.tid.es/browse/AURA-13210"
teams:
  bot:
    update_dependencies: []
    repositories:
      - aura-aog-bridge
      - aura-services-api
      - aura-bot-common
      - aura-clients
      - aura-bot-libraries
      - aura-bot-libraries-test
      - aura-bot-platform
      - aura-bridge
      - aura-code-generator
      - aura-locale-importer
      - aura-movistar-libraries-utilities
      - aura-terms-and-conditions-api
      - aura-utilities
      - aura-kpis-uploader
      - aura-docs
    node_version: 14
    dependencies:
      - name: baikal-sdk
        version: 0.10.1
      - name: baikal-sdk
    tools:
      po_editor:
        project_base: Aura-Bot
    protection:
      restrictions:
        users: []
        teams:
          - aura-ci
          - aura-bot-global-dev
          - aura-bot-ext-devs
        apps: []
    stages:
      init:
        - install-dependencies
        - create-branch
        - store-locales
        - prepare-repository
        - create-changelog
        - protect-branch
        - install-tools
      start:
        - unprotect-branch
        - trigger-deploy-components
        - protect-branch
        - validate-deploy-components
      prepare-to-merge:
        - update-locales
        - check-conflicts
        - merge-and-update-versions
        - publish-modules
        - trigger-deploy-components
        - validate-deploy-components
      close:
        - unprotect_branch
        - prepare-versions-to-master
        - merge-to-master
        - validate-deploy-components
      finalize:
        - remove-main-branches
        - uninstall-tools
        - remove-packages
    tasks:
      - Review documentation before closing
      - Review PoEditor content before closing
      - Review performance before closing
  devops:
    repositories:
      - aurak8s
    stages:
      init:
        - create-branch
        - initial-commit
        - check-environment
        - create-environment
        - deploy-environment
        - unprotect-tests-branch
        - upload-environment-files
        - protect-tests-branch
        - protect-branch
      prepare-to-merge:
        - check-conflicts
        - merge
      close:
        - check-environment
        - close-environment
        - delete-environment
        - merge-to-master
    protection:
      restrictions:
        users: []
        teams:
          - aura-ci
          - aura-devops-admin
          - aura-global-cto
        apps: []
  qa:
    repositories:
      - aura-tests
    protection:
      required_status_checks:
        strict: false
        contexts: ['continuous-integration/jenkins/pr-head']
      enforce_admins: true
    tests:
      smoke_tests_enabled: false
      wa_mobile_tests_enabled: false
    stages:
      init:
        - create-branch
        - prepare-repository
        - protect-branch
      start:
        - sanity-tests
      prepare-to-merge:
        - unprotect-branch
        - check-conflicts
        - merge
        - protect-branch
        - smoke-tests
      close:
        - unprotect-branch
        - restore-repository
        - unprotect-master
        - merge-to-master
        - protect-master
        - smoke-tests

  nlp:
    repositories:
      - aura-cognitive-container
    repository_components: complex_logic,context-4p-synchronizer,context_provisioning,context,nlp-provisioning,nlp
    stages:
      init:
        - create-branch
      prepare-to-merge:
        - check-status-container
      close:
        - merge-to-master
    tasks: []

  training_nlp:
    repositories:
      - aura-nlpdata-es
    release_branch: release/7.0
    stages:
      init:
        - create-branch
      prepare-to-merge:
        - create-all-main-prs
        - check-status-repositories
      close:
        - merge-to-master
    tasks: [ ]

  legacy:
    repositories:
      - aura-cognitive-containers
    protection:
      restrictions:
        users: []
        teams:
          - aura-ci
          - aura-platform-tech-leads
          - aura-global-cto
        apps: []
    stages:
      init:
        - create-branch
        - prepare-repository
        - protect-branch
      prepare-to-merge:
        - check-conflicts
        - unprotect-branch
        - merge
        - protect-branch
      close:
        - unprotect-branch
        - update-version
        - unprotect-master
        - merge-to-master
        - protect-master

main_protection:
  restrictions:
    users: []
    teams:
      - aura-ci
      - aura-global-cto
    apps: []

protection:
  required_status_checks:
    strict: false
    contexts: []
  enforce_admins: false
  required_pull_request_reviews:
    dismissal_restrictions:
      users: []
      teams:
        - aura-ci
    dismiss_stale_reviews: true
    require_code_owner_reviews: true
    required_approving_review_count: 2
    bypass_pull_request_allowances:
      users: []
      teams:
        - aura-ci
  restrictions:
    users: []
    teams: []
    apps: []
  required_linear_history: false
  allow_force_pushes: false
  allow_deletions: false
  block_creations: false
  required_conversation_resolution: false

2.1 - Main branch stages

Main branches stages

Description of the different stages for main branches in the Release Train Manager

The following diagram shows the Release Train Manager stages for main branches:

All phases of the main branches are managed by the workflow: .github/workflows/push-to-main.yml.

name: Push To Main
on:
  push:
    branches:
      - "main/**"
      - "hotfix/**"

jobs:
  load-configuration:
  ########
  # INIT #
  ########
  prepare-init-process:
  protect_branch_main:
  init-bot-module:
  init-devops-module:
  init-legacy-module:
  init-models-module:
  init-nlp-module:
  init-training-nlp-module:
  init-qa-module:
  #########
  # START #
  #########
  start-bot-module:
  start-qa-module:
  ####################
  # PREPARE TO MERGE #
  ####################
  block-close:
  prepare-to-merge-bot-module:
  prepare-to-merge-training-nlp-module:
  prepare-to-merge-qa-module:
  prepare-to-merge-legacy-module:
  prepare-to-merge-devops-module:
  #########
  # CLOSE #
  #########
  close-bot-module:
  close-devops-module:
  close-qa-module:
  close-legacy-module:
  close-nlp-module:
  close-training-nlp-module:
  ############
  # FINALIZE #
  ############
  finalize-bot-module:

  process-result:

Main Init stage

In this phase, the branches are generated in the repositories and, if there is a configured environment, it will be deployed. As in every stage, each team defines its own steps, but some of them are shared and executed by any of the teams.

Common steps

Create branch

This step gets the list of repositories of the team (from branch-config.yml file, teams.*.repositories) which step is being executed and creates the corresponding main branch in all of them. If the branch already exists, it just goes on.

Protect Branch

Once all the initial changes are applied in each package of each main branch, they are protected to force the creation of a Pull Request to merge changes on them. It is executed after every stage of the RTM, because it needs the branch to be unprotected during its execution, to make changes automatically.

Unprotect Branch

RTM stages need to remove repositories’ branches protection to apply changes automatically in the code. It is executed at the beginning of almost any stage of the RTM.

Check conflicts

This step is executed during prepare-to-master stage to check if there is any conflict between master and the main branch in any configured repository. Any conflict will be reflected in the RTM as a message in the corresponding PR.

Init Bot Steps

Bot: Install dependencies

In this step, the dependencies defined in teams.bot.dependencies are installed. The tgz of the NPM module is obtained and installed in the Github repository. This is necessary because the main branch works in isolation and uses Github as the main repository.

Bot: Store Locales

In this step, all the locales files of every package in every repository are stored in DB. They are stored in the collection called branch-locales.

Bot: Prepare Repository

In this step, all the dependencies of every package in every repository are updated. Internal node packages (those belonging to @telefonica NPM organization) in master branch are read from npm registry and a x.y.z version is used. But each main branch uses for the internal dependencies a private GitHub npm registry and the dependencies are tagged with the decodedName of the branch: version: 7.5.0-main-my-feature.0.

Packages are read in order, so first those packages without internal dependencies are processed. They are published in GitHub registry and those packages depending on them are then processed, going on recursively.

Bot: Create Changelog

This step is responsible for creating the changelog scaffolding for the current version.

Bot: Install Tools

A new project is created in POEditor to include the language resources to be contained in this main branch. The project is created by auradev@tid.es user and its name will be the branch decoded name: main/feature-desc#id -> main-feature-desc-id. This project is intended to contain all the changes (creations or updates) of locales for the issues being resolved in this main branch.

Main Start stage

In this phase, all the components configured in branch-config.yml and that were prepared during the init stage will be deployed if an environment has been configured for the current branch. Afterwards, the sanity test plan is launched just to validate that the environment is properly settled. If no environment is configured (for instance, if a branch is just to review documentation or to prepare something specifically for a given OB, such as language trainings) tests are not executed.

Start Bot Steps

Bot: Trigger Deploy Components

A push is launched in the repositories of the components to force them to be deployed from CI job running in Jenkins. After each component is deployed, Jenkins sends a notification to GitHub to inform of the status, that is updated in the RTM API database.

Bot: Validate Deploy Components

This step is in charge of validating that all the components that are configured for the current branch have been deployed. It reads the information from the RTM API database that is updated with every notification from Jenkins, as explained in the previous step.

Main Prepare-To-Merge stage

This phase aims to merge master changes in the current main branch, deploy the updated version in the branch in configured environment, if exists, and launch the complete functional test plan to validate the full code base before merging to master.

Prepare-To-Merge Bot Steps

Bot: Update Locales

This step is in charge of updating the locales files in all repositories doing a merge into the main poEditor project and Aura-Bot PoEditor project.

Bot: Merge and Update Versions

Once the eventual conflicts have been resolved in all repositories configured in the branch, the content of master and main branches are merged together. In the happening of any change, tagged versions are automatically updated to provoke a new deployment of the components.

Bot: Publish Modules

If new versions have been generated in any of the bot npm libraries, a new version of them is published and updated in all the components.

Main Close stage

In this phase, all the components will be deployed in master and the libraries published in NPM. The versions of the modules will be updated if the repositories have been changed along the development in the main branch.

Close Bot Steps

Bot: Prepare versions to master

As already mentioned, bot versions in master are not tagged but in x.y.z format. This step calculates the next version of each library and component automatically depending on the existing version in master, the original semantic version and the number of changes in its tagged version in the main branch. If a library or a component has been updated in a main branch, no matter the number of commits needed for the change, its semantic version in master will be increased by 1 in the minor counter. For instance, if the version in master for library my-library is 6.2.0, and my-library has some changes in the current branch, its version in master after merging the main branch, will be 6.3.0.

Bot: merge to master

If new versions have been generated in the libraries, changes are merged and the libraries are published in @telefonica private npm registry.

Finalize step

In this phase, all the branches created, packages installed in Github and the POEditor project are deleted.

Finalize Bot Steps

Bot: Remove Main Branches

The main branch created in the repositories is removed.

Bot: Uninstall Tools

This step removes the POEditor project created for the language resources of this main branch.

Bot: Remove Packages

This step removes the packages created in the branch for each library.

3 - Managing locales

Managing locales in RTM

How locales files and POEditor project are managed in RTM.

How to manage locales

  • To avoid updating the locales with the base project in the main branches in the RTM INIT process, there is a job store-locales, that is responsible for storing the locales of each component/library in the branch-locales collection with the following structure:
{
   "branch": "main/fake",
   "authentication-api": {
        "de-de": "{\n \"authentication:authenticator-error.description\": [\n \"Bei der Authentifizierung ist ein Fehler aufgetreten. Bitte versuche es später noch einmal\"\n ],\n ....",
        "es-cr": "{\n \"authentication:A1004.authenticator-error.description\": [\n \"Parece que has olvidado tu usuario o contraseña de acceso a Mi Movistar.\"\n ] ....}"
   },
    "aura-bot-platform": {
        "es-cr": "{\n \"context-filter:multimsisdn-users-not-allowed.onboarding\": [\n \"Pulsa el micrófono y di lo que quieras. Consulta la ayuda para saber qué cosas puedes preguntarme.\"\n ],\n \"context-filter:user-info-not-accessible\": [\n \"Sorry\"\n ],\n \"core:bypass.close.words\": [\n \"cancelar\",\n \"cerrar\",\n \"salir\",\n \"desconectar\"\n ],\n \"core:empty.response\": [\n \"Ok, estarei aqui sempre que você precisar.\"\n ] }\n",
        "de-de": "{\n \"context-filter:multimsisdn-users-intent-not-allowed.text\": [\n \"Entschuldigung, auf diese Daten kann ich aufgrund deines Vertrages nicht zugreifen. Zukünftig kann ich das sicherlich, aber bis dahin kann ich dir mit Fragen rund um o2 Services weiterhelfen. Wenn du mehr Informationen über deinen Vertrag erhalten möchtest, gehe einfach in deinen [Mein o2 Bereich](www.o2online.de/meino2).\"\n ],\n \"context-filter:user-info-not-accessible\": [\n \"Sorry\"\n ],\n \"core:bypass.close.words\": [\n \"cancelar\",\n \"cerrar\",\n \"salir\",\n \"desconectar\"\n ],\n \"core:empty.response\": [\n \"Ok, estarei aqui sempre que você precisar.\"\n ] }\n"
     }
}
  • During the development of the main branch, if it is necessary to update the locales of any component, it will be done using the locale-update script, which will have been updated by the following locale-importer command in the creation phase of the branches of each component/library:
aura-locale-importer -u -s Db -pkg <package_name> -m library -b core -d ./locale -f -mb <main-branch-name>
The environment variables SECRET_TOKEN and BRANCH_CONFIG_APIKEY are required for its execution.

This command will do a merge between the local files stored in DB for that component/library and the resources created/updated in the POEditor project main-branch-name generating the new locales files.

  • In the execution of the prepare-to-merge of the bot, an update-locales step has been added, which updates the locales of each component/library by merging the content of the base project in POEditor (Aura-Bot) with the POEditor project of the main branch.

Endpoints locales

For the management of the locales in BD, the following endpoints have been created in aura-release-train-branches: - /branches/{branch}/locales - /branches/{branch}/locales/{package}

4 - API definition

Release Train Manager API definition

Description of Release Train Manager API

This API is used to manage the release train process and stores both the configuration and state of all the main/hotfix/release/fasttrack branches handled by the release train manager, but also the status of the environments: component versions deployed, if any component has a new version waiting to be deployed, etc.

The API is used both from the release train manager and from the Jenkins CI jobs themselves.

Download swagger file