Wie kann ich IF ELSE in Variablen der Azure DevOps Yaml-Pipeline mit Variablengruppe verwenden?

8

Ich versuche, einer Variablen zusätzlich zur Variablengruppe einen von zwei Werten zuzuweisen, und kann die Referenz zur Verwendung von IF ELSE nicht finden.

Grundsätzlich muss ich diese Wamslogik in azurblaue DevOps konvertieren.

Jenkins

if (branch = 'master') { 
   env = 'a'
} else if (branch = 'dev'){
    env ='b'
}

Ich habe 1 Referenz aus der folgenden gefunden, aber diese scheint zu funktionieren, wenn der Variablenabschnitt keine Variablengruppen enthält.

https://stackoverflow.com/a/57532526/5862540

Aber in meiner Pipeline habe ich bereits eine Variablengruppe für Geheimnisse, daher muss ich die Name / Wert-Konvention verwenden und das Beispiel funktioniert nicht mit den Fehlern wie expected a mappingoder A mapping was not expectedoderUnexpected value 'env'

variables:
- group: my-global
- name: env
  value:
    ${{ if eq(variables['Build.SourceBranchName'], 'master') }}: 
      env: a
    ${{ if eq(variables['Build.SourceBranchName'], 'dev') }}: 
      env: b

oder

variables:
- group: my-global
- name: env
  value:
    ${{ if eq(variables['Build.SourceBranchName'], 'master') }}: a
    ${{ if eq(variables['Build.SourceBranchName'], 'dev') }}: b

kevmando
quelle
Eine Problemumgehung, die ich jetzt habe, ist das Kopieren des Variablenabschnitts mit Ausdruck in alle Jobs, die ich benötige. Aber ich möchte es einfach globale Variable machen.
Kevmando

Antworten:

1

Ich denke, für den Moment müssen Sie eine Aufgabe verwenden, um sie mit name/valueSyntaxvariablen und bedingten Variablenwerten anzupassen. Es sieht so aus, als ob die Objektstruktur für die name/valueSyntax das Parsen von Ausdrücken unterbricht, wie Sie bereits betont haben.

Für mich ist das Folgende eine einigermaßen saubere Implementierung, und wenn Sie es von der Pipeline abstrahieren möchten, sollte eine einfache Vorlage für Ihre vielen Pipelines den Wunsch nach einem zentralen "globalen" Standort befriedigen.

variables:
  - group: FakeVarGroup
  - name: env
    value: dev

steps:
  - powershell: |
      if ($env:Build_SourceBranchName -eq 'master') {
        Write-Host ##vso[task.setvariable variable=env;isOutput=true]a
        return
      } else {
        Write-Host ##vso[task.setvariable variable=env;isOutput=true]b
      }      
    displayName: "Set Env Value"
Josh Gust
quelle
Danke für den Vorschlag. Ich glaube, ich hatte von hier aus eine ähnliche Lösung gesehen, aber nicht versucht, weil ich hoffe, dass es eine einfachere Lösung geben würde, ohne einen Schritt hinzuzufügen. Ich habe auch den MS-Support gefragt. Wenn sie keine Lösung haben, werde ich dies versuchen.
Kevmando
Ich hatte E-Mails mit dem MS-Support ausgetauscht und sie schlugen diese Problemumgehung vor und baten mich, einen Funktionsvorschlag für die MS-Entwicklergemeinschaft einzugeben. Also werde ich dies jetzt als Antwort markieren.
Kevmando
0

Soweit ich weiß, ist der beste Weg, um eine bedingte Verzweigung zu erstellen, die Verwendung von "Trigger" in Ihrer YAML, anstatt ein komplexes "if-else" zu implementieren. Es ist auch viel sicherer und Sie haben explizitere Steuerelemente für die Verzweigungsauslöser, anstatt sich auf CI-Variablen zu verlassen.

Beispiel:

# specific branch build 
jobs:
- job: buildmaster
  pool:
    vmImage: 'vs2017-win2016'
  trigger:
    - master

  steps:
  - script: |
      echo "trigger for master branch"

- job: buildfeature
  pool:
    vmImage: 'vs2017-win2016'
  trigger:
    - feature

  steps:
  - script: |
      echo "trigger for feature branch"

Um einen Trigger mit Einschluss und Ausschluss von Zweigen zu haben, können Sie eine komplexere Syntax des Auslösers mit Einschluss und Ausschluss von Zweigen verwenden.

Beispiel:

# specific branch build
trigger:
  branches:
    include:
    - master
    - releases/*
    exclude:
    - releases/1.*

Die offizielle Dokumentation zu Azure DevOps-Pipelines triggerin YAML lautet: Dokumentation zu Azure Pipelines YAML-Triggern

UPDATE 1 :

Ich poste meinen Kommentar hier mit zusätzlichen Anmerkungen: Ich dachte, ich hätte verschiedene Pipelines, weil die Komplexität des Jonglierens zwischen CI-Variablen nicht besser zu warten ist als mehrere Jobs in einer YAML mit Triggern. Multijobs mit Triggern zwingen uns auch dazu, eine klare Unterscheidung und Bereitstellung für das Filialmanagement zu treffen. Auslöser und bedingte Verzweigungseinschlüsse werden von meinem Team aufgrund dieser Wartbarkeitsvorteile seit einem Jahr verwendet.

Sie können dem gerne widersprechen, aber für mich ist es eher eine Ad-hoc-Lösung, wenn in einem Skript eine eingebettete Logik vorhanden ist, um zu überprüfen, welcher Zweig sich gerade in der Sitzung befindet und dann weitere Aktionen ausführt. Und das hat meinem Team und mir schon früher Wartungsprobleme bereitet.

Insbesondere wenn die eingebettete Logik dazu neigt, durch Überprüfen anderer Zweige zu wachsen, ist die Komplexität später komplexer als klare Trennungen zwischen Zweigen. Auch wenn die YAML-Datei für längere Zeit aufbewahrt werden soll, sollte sie klare Bestimmungen und Roadmaps für verschiedene Branchen enthalten. Redundanz ist unvermeidlich, aber die Absicht, bestimmte Logik zu trennen, zahlt sich auf lange Sicht mehr für die Wartbarkeit aus.

Deshalb betone ich in meiner Antwort auch Ein- und Ausschlüsse von Zweigen :)

Eriawan Kusumawardhono
quelle
Vielen Dank für den Vorschlag, aber meine Pipeline hat Trigger bereits für andere Zwecke verwendet. (Um ehrlich zu sein, fühlt sich die Triggerfunktion selbst im Vergleich zu Jenkins weniger flexibel an. Es ist schwierig, die Bedingungen wie das Abbrechen des duplizierten pr / branch-Builds usw. zu implementieren.) Außerdem wird es zu viele redundante Leitungen geben, wenn ich muss Wiederholen Sie dieselben Jobs erneut, um einen einzelnen Wert pro Zweig zu ändern. (Ich kann auch umgehen, um Variablenabschnitte zu wiederholen, was weniger redundanter Code wäre.)
kevmando
Vielleicht muss ich über den Tellerrand hinausdenken, da es nicht Jenkins ist, aber das Team möchte keine neue Pipeline ohne offensichtlichen Vorteil haben.
Kevmando
Neue Pipeline? Nein. Diese YAML befindet sich in einer Datei und kann daher in einer Pipeline verwendet werden, die viele Zweige bedienen kann.
Eriawan Kusumawardhono,
Was ich als neue Pipeline gemeint habe, ist, dass ein neuer Workflow anders funktioniert als der vorherige Workflow. Nicht mit diesem Thema verbunden, aber mehr Triggeroptionen, da es hier erwähnt wurde.
Kevmando
OP fragt nicht, wie ein Build basierend auf einem Verzweigungswert ausgelöst werden soll. Die gestellte Frage war, wie ein variabler Wert basierend auf dem Kontext, in dem die Pipeline ausgelöst wird, an Bedingungen geknüpft werden kann. Ihre Lösung, wenn sie auf die tatsächlich gestellte Frage angewendet wird, zwingt OP, 2 Pipelines zu erstellen. 1) trigger = master & env = a 2) trigger = dev & env = b.
Josh Gust