YAML Build: VM Image via Parameter wechseln

In einem Capacitor Projekt haben wir implementiert, dass der Web-App Teil davon von der Nativen Container App selbst upgedated wird und wollten daher meist nur den Web-Teil bauen und fürs Update verpacken.

Das bauen der App "verschlingt" relativ viel Build-Zeit, was wenn man im App teil nichts geändert hat relativ sinnlos ist.

 

Daher gabs folgendes Scenario - der Web Teil wird im CI Build automatisch getriggert - der App Teil mit dem Capacitor Build, anschließendem signieren und so aber nur per Parameter.

Dazu musste auch berücksichtigt werden, dass der Web teil damit auf einem einfachen (und viel schnelleren) ubuntu-latest vmImage Agent gebaut werden kann, während die App im macos-latest Image gebaut wird (sowohl Android als auch iOS).

 

Wie kann man das in einem Azure DevOps YAML Build lösen ?

Es hat mich ein wenig Zeit gekostet, daher wirds hier festgehalten 😉.

Zuerst brauch ma einen Parameter, welcher sagt ob die mobile App gebaut werden soll oder nicht:


parameters:
- name: BuildConfiguration
  type: string
  default: Release
  values:
   - Release
   - Debug
- name: BuildMobileApp
  type: boolean
  default: false

 

und jetzt kommt der Trick:

Damit wir im Job das VM Image wechseln können brauchen wir vorab einen Job welcher das vmImage für den Build ermittelt:

jobs:
  - job: Check_Vars
    pool:
      vmImage: 'ubuntu-latest'
    steps:
      - checkout: none
      - script: if [ "${{ parameters.BuildMobileApp }}" == "True" ]; then echo "##vso[task.setvariable variable=buildVmImage;isoutput=true]macos-latest"; else echo "##vso[task.setvariable variable=buildVmImage;isoutput=true]ubuntu-latest"; fi
        name: produceVar 

Der Job macht nur ein kleines bash script welches schaut ob die der Parameter gesetzt ist und setzt eine Output-Variable für den nächsten Job mit dem namen vom Pool.

Wichtig ist noch das checkout: none weil wir ja keinen ausgecheckten Code brauchen.

 

Das muss jetzt nochmal dem neuen Job gefüttert werden :

  - job: Build_App
    dependsOn: Check_Vars
    variables:
      buildVmImage: $[ dependencies.Check_Vars.outputs['produceVar.buildVmImage'] ]
    pool:  
      vmImage: $(buildVmImage)

 

zuerst definieren wir dass der Build_App job den Check_Vars braucht. Dann lesen wir den Output des jetzten Jobs aus und setzten diese in eine Variable, welche dann in dem vmImage des Pools verwendet wird - direkt geht es leider nicht, da er dort die Auswertung der Expression nicht macht.

Fertig - es geht 😊

Zuletzt müssen jetzt nur mehr alle Tasks mit die zum Bauen der App gehören noch deaktivert werden, falls wir keine App bauen wollen.

    - task: ios-bundle-version@1
      displayName: 'set iOS app version'
      condition: eq('${{ parameters.BuildMobileApp }}', true)
1.png

In der Initialisierung sieht man wie die Parameter aus dem Job ausgewertet werden.

3.png

Hier mit macOS - hier wird die App gebaut

4.png

Hier mit ubuntu-Image - da werden auch alle Steps übersprungen die nicht gebraucht werden.