← zurück zum Blog

Anchors: DRY YAMLs für CI/CD-Pipelines

Pipelinekonfigurationen beinhalten oftmals viele wiederholte Steps. In diesem Guide wird erklärt, wie man dieses Problem mit YAML Anchors verhindern kann und gleichzeitig die Konfigurationsdatei übersichtlicher und weniger fehleranfällig gestaltet.
Markus Heer
Markus Heer15. August 2020

Einführung

Die YAML-Konfigurationen für CI/CD-Pipelines sind selbst für kleine Projekte oft durch wiederholte Steps geprägt. Meist sind diese Steps für alle Umgebungen gleich oder enthalten lediglich minimale Änderungen. Um diesen Misstand zu beseitigen, können sogenannte Anchors verwendet werden. Dies wird in diesem Artikel am Beispiel von Bitbucket Pipelines demonstriert, lässt sich aber problemlos auch auf andere konfigurationsbasierte Pipelines - wie etwa die von GitLab - anwenden.

Eine typische Pipelinekonfigu­ration

In einem üblichen JavaScript-Projekt könnte eine Pipeline mit Installations-, Test- und Build-Step wie folgt aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
image: node:latest

pipelines:
  develop:
    - step:
        name: Install
        caches:
          - node
        script:
          - npm i
    - step:
        name: Test
        caches:
          - node
        script:
          - npm test
  master:
    - step:
        name: Install
        caches:
          - node
        script:
          - npm i
    - step:
        name: Test
        caches:
          - node
        script:
          - npm test
    - step:
        name: Build
        caches:
          - node
        script:
          - npm run build

Vermeiden von Wiederholungen mit Anchors

Hier sieht man schnell das Optimierungspotential. Master und Develop-Branch teilen sich identische Steps. Mittels Anchors (&Anchor) können wir diese Steps ein Mal definieren und dann in beiden Steps ausgeben (*Referenz). Dieses würde in obigem Beispiel wie folgt aussehen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
image: node:latest

definitions:
  steps:
    - step: &Install
        name: Install
        caches:
          - node
        script:
          - npm i
    - step: &Test
        name: Test
        caches:
          - node
        script:
          - npm run build

pipelines:
  develop:
    - step: *Install
    - step: *Test
  master:
    - step: *Install
    - step: *Test
    - step:
        name: Build
        caches:
          - node
        script:
          - npm run build

Wie man sehen kann, wurde ein definitions Map hinzugefügt. Hier werden alle Anchors gehalten. Dies ist eine Bitbucket-Spezialität, für Anchors im generellen tut das aber nichts zur Sache. Definiert man einen Anchor (z.B. &Install) wird dieser Konfigurationsblock verfügbar gemacht, sobald man auf ihn referenziert (z.B. mit *Install).

Verändern von Anchor-Werten

Möchten wir nun beispielsweise auf mehreren Branches den selben Step ausführen, ihn jedoch leicht verändern, kann man dies wie folgt tun:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
image: node:latest

definitions:
  steps:
    - step: &Install
        name: Install
        caches:
          - node
        script:
          - npm i

pipelines:
  develop:
    - step: *Install
  master:
    - step: 
        <<: *Install
        name: Install for Master

Wie man sieht, kann man mit dem << Operator Konfigurationen übernehmen und im Anschluss Werte von bestimmten Keys überschreiben.

Fazit

Wer bereits an Konfigurationen für viele Umgebungen gearbeitet hat, weiß, dass leicht Fehler passieren, wenn man an vielen Stellen den gleichen Step bearbeiten muss. Mittels YAML-Anchors können Konfigurationen übersichtlicher gestaltet und vor allem Fehler vermieden werden.

© 2020 - Code: byteleaf - Design: Michael Motzek