Contents

Generate PlantUML in you CI/CD Pipeline

This is part of a series creating around PlantUML and Diagrams as Code.

  1. Authoring Plant UML files in Visual Studio Code
  2. Creating Image file from PlantUML using command line
  3. Creating Pipeline to build and check-in Diagrams as Code (This Post)
  4. Optimise the Pipeline

In the previous posts in the series we have looked how to author as well as how to build the PlantUML files using command line tools.

In this post will we build the PlantUML diagrams on check-in.

Getting started

Step 1 - Setup Azure DevOps Project to enable build agent

We are going to configure Azure DevOps Pipeline to build the PNG when we check in the wiki. So the PNG needs to be added to the Repository. Configure the security for the given project follow the steps in this tip https://azuredevops.tips/2020/02/29/repo-allow-build-agent-to-commit-code/ .

Step 2 - Configure Pipeline

  1. Create new Pipeline /generateplantumlinpipeline-yaml/image1.png

  2. Select the location where your PlantUML documents are located. /generateplantumlinpipeline-yaml/image2.png

  3. Create Starter Pipeline /generateplantumlinpipeline-yaml/image3.png

Pipeline to generate PlantUML diagrams

Build PNG files from PUML

 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
pool:
  vmImage: 'vs2017-win2016'
trigger:
 batch: true
workspace:
    clean: all
    
steps:
- checkout: self
  persistCredentials: true
- task: [email protected]
  displayName: Install Node
  inputs:
    version: '6.x'
- task: [email protected]
  displayName: Install Node Plant UML
  inputs:
    command: 'custom'
    customCommand: 'install node-plantuml -g' 
- task: [email protected]
  displayName: Check Out
  inputs:
    targetType: 'inline'
    script: |
            git config --global user.email "[email protected]"
            git config --global user.name "Your Name"
            git status
            
            git checkout "$Env:BUILD_SOURCEBRANCHNAME"

- task: [email protected]
  displayName: Build Images
  inputs:
    targetType: 'inline'
    script: |
            $sourceRoot = "$Env:Build.SourcesDirectory"
            Get-ChildItem $sourceDir -Recurse -Filter "*.puml" |
                Foreach-Object   {
                    $fileWithPath = $_.Fullname         
                    $png =  Join-Path  -Path $_.DirectoryName -ChildPath ("{0}.png" -f $_.Basename ) 
                    $execute = "puml generate $fileWithPath -o $png "; 
                    Invoke-Expression -Command $execute 
                }

- task: [email protected]
  displayName: Check In
  inputs:
    targetType: 'inline'
    script: |
            git add --all
            git commit -m "$Env:BUILD_BUILDNUMBER [skip ci]"
            #git checkout "$Env:BUILD_SOURCEBRANCHNAME"
            #git merge "$Env:BUILD_SOURCEBRANCHNAME" -m "$Env:BUILD_BUILDNUMBER"
            #git branch -d "$Env:BUILD_BUILDNUMBER"
            git push origin  
          

Double check Security

The build agent security needs to be configured properly look at https://azuredevops.tips/allow-build-agent-to-commit-code/ this will give the instructions on how to enable the right security settings.

If these settings are set you the pipeline won’t be able to check in the images.

Break it Down

  1. Define Windows Build Agent
1
2
3
4
5
6
7
8
9
# Pipeline to generate PlantUML diagrams
# Build PNG files from PUML

pool:
  vmImage: 'vs2017-win2016'
trigger:
 batch: true
workspace:
    clean: all

Specify a Windows build agent, at the moment this script only works on Windows, I have yet to get it working on other platforms. The build agent will clear out all the content on the build agent, it will also make sure that if multiple changes happen in a short period it will batch up these changes.

  1. dfd
1
2
- checkout: self
  persistCredentials: true

Persist Credentials, enables the pipeline to use OAuth token to check in the new PNGs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- task: [email protected]
  displayName: Install Node
  inputs:
    version: '6.x'
- task: [email protected]
  displayName: Install Node Plant UML
  inputs:
    command: 'custom'
    customCommand: 'install node-plantuml -g' ```

Install Node and the node-plantuml command line.

  • task: [email protected] displayName: Check Out inputs: targetType: ‘inline’ script: | git config –global user.email “[email protected]” git config –global user.name “Your Name” git status

          git checkout "$Env:BUILD_SOURCEBRANCHNAME"
    
1
2
3
4

Powershell script configure the git then Check Out the selected branch.


  • task: [email protected] displayName: Build Images inputs: targetType: ‘inline’ script: | $sourceRoot = “$Env:Build.SourcesDirectory” Get-ChildItem $sourceDir -Recurse -Filter “*.puml” | Foreach-Object { $fileWithPath = $_.Fullname
    $png = Join-Path -Path $_.DirectoryName -ChildPath ("{0}.png” -f $_.Basename ) $execute = “puml generate $fileWithPath -o $png “; Invoke-Expression -Command $execute }
1
2
3
4


Powershell script to loop over all the folders to find all files with puml extension. For all the files run puml cli to generate the png files.

  • task: [email protected] displayName: Check In inputs: targetType: ‘inline’ script: | git add –all git commit -m “$Env:BUILD_BUILDNUMBER [skip ci]” git push origin
1
2
3
4

Add all the new files generated. Commit the changes, note the [skip ci] on the commit, this means that the pipeline won't be triggered again for the checked in PNGs. The script then pushes in the changes to the server.


# Starter pipeline# Start with a minimal pipeline that you can customize to build and deploy your code.# Add steps that build, run tests, deploy, and more:# https://aka.ms/yaml
trigger:  batch: true  paths:    include:    - plantuml/*    exclude:    - wiki/*
pool:  vmImage: ‘windows-2019'
steps: - checkout: self  persistCredentials: true  clean: true- task: [email protected]  displayName: Check for Changed YAML  inputs:    targetType: ‘inline’    script: |        Write-Output "##vso[task.setvariable variable=continue]false”      $files=$(git diff HEAD HEAD~ –name-only)      $temp=$files -split ' '      $count=$temp.Length      For ($i=0; $i -lt $temp.Length; $i++)      {        $name=$temp[$i]        if ($name.EndsWith('.puml’))        {          echo “this is $name file”          Write-Output "##vso[task.setvariable variable=continue]true”          Break        }      }
- task: [email protected]  displayName: Install Node  inputs:    version: ‘6.x’  condition: eq(variables[‘continue’],‘true’)
- task: [email protected]  displayName: Install Node Plant UML  inputs:    command: ‘custom’    customCommand: ‘install node-plantuml -g’   condition: eq(variables[‘continue’],‘true’)
- task: [email protected]  displayName: Install PlantUML Latest and GraphViz  inputs:    targetType: ‘inline’    script: |            choco install graphviz            choco install plantuml  condition: eq(variables[‘continue’],‘true’)
- task: [email protected]  displayName: Build Images just for the changed Puml  inputs:    targetType: ‘inline’    script: |         git config –global user.email “[email protected]”      git config –global user.name “Your Name”      # if ($Env:BUILD_SOURCEBRANCH -eq “refs/heads/master”)       # {      #   Write-Host “Building master branch so no merge is needed."      #   exit      # }      # $sourceBranch= “origin/$Env:BUILD_SOURCEBRANCH:refs/heads/=”            # $editedFiles = git diff HEAD HEAD~ –name-only      # $editedFiles | ForEach-Object {      # Switch -Wildcard ($_ ) {      #  ‘SubFolderA/*' { Write-Output "##vso[task.setvariable variable=MicroserviceA]True” }        # The rest of your path filters      #    }      # }            git branch  “$Env:BUILD_BUILDNUMBER”      git checkout “$Env:BUILD_BUILDNUMBER” -q      #git checkout master      $files=$(git diff HEAD HEAD~ –name-only)      $temp=$files -split ' '      $count=$temp.Length      For ($i=0; $i -lt $temp.Length; $i++)      {        $name=$temp[$i]        if ($name.EndsWith('.puml’))        {          $fileWithPath = $name           $png =  Join-Path  -Path (Get-Item $fileWithPath).DirectoryName -ChildPath ("{0}.png” -f (Get-Item $fileWithPath).Basename )           Write-Host $png           $execute = “puml generate $fileWithPath -o $png ";           Invoke-Expression -Command $execute         }      }             git add –all      git commit $sourceBranch -m “Add Generated Images-[ci skip]"      git checkout ${Env:BUILD_SOURCEBRANCHNAME} -q      git merge “$Env:BUILD_BUILDNUMBER”  -q      git push  -q

1
2
3
4