• info@noobygames.de

Automatically create a changelog using Azure DevOps

azure devops meme

Automatically create a changelog using Azure DevOps

There is a point in the live of every developer, where you have to maintain a changelog. Let's be honest, most of us start by manually creating a changelog. And then you forget to update the changelog from time to time, this is where your customer start to call your support and you start to cry. So you change your processes, add checklists, that you manually check and we all know that every time you have to manually maintain the changelog a little tear makes it all the way from your sad eye to your chin and silently drops into the darkness as you try to think of a good description for your change. BUT CRY NO MORE! You can easily automatically create a changelog using Azure DevOps

At Clarilab i have the possibility to do cool stuff. So i took some time to check out some possibilities to automate that whole tear shredding process. What follows is an explanation of our first attempt to automatically create the changelog, using build pipelines and 2 extensions.

XplatGenerateReleaseNotes

The first extension that we use is XplatGenerateReleaseNotes from Richard Fennel. It allows us to use a HandleBar template to define the content and style of the changelog.

So install the XplatGenerateReleaseNotes plugin using the link above.
Now add a Task to your build OR release pipeline and chose.
XplatGenerateReleaseNotes

You need to specify the path for the artifact. In our exmaple we chose System.DefaultWorkingDirectory so we have access to the file in the next step.

outputfile: '$(System.DefaultWorkingDirectory)\releasenotes.md'

You can either specify the template in a file in your repository, or inline. In our example we chose inline.

templateLocation: 'InLine'

Explanation of all arguments is here

Example Configuration


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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
- task: XplatGenerateReleaseNotes@3
  inputs:
    outputfile: '$(System.DefaultWorkingDirectory)\releasenotes.md'
    outputVariableName: 'kycnow-dev-release'
    templateLocation: 'InLine'
    inlinetemplate: |
      **Release Notes**

      # Notes for release  {{releaseDetails.releaseDefinition.name}}    
      **Release Number**  : {{releaseDetails.name}}

      **Release completed** : {{releaseDetails.modifiedOn}}    

      **Build Number**: {{buildDetails.id}}

      **Compared Release Number**  : {{compareReleaseDetails.name}}  

      **Build Trigger PR Number**: {{lookup buildDetails.triggerInfo 'pr.number'}}

      # Associated Pull Requests ({{pullRequests.length}})
      {{#forEach pullRequests}}
      {{#if isFirst}}### Associated Pull Requests (only shown if  PR) {{/if}}
      *  **PR {{this.id}}**  {{this.title}}
      {{/forEach}}

      # Builds with associated WI/CS/Tests ({{builds.length}})
      {{#forEach builds}}
      {{#if isFirst}}## Builds {{/if}}
      ##  Build {{this.build.buildNumber}}
      {{#forEach this.commits}}
      {{#if isFirst}}### Commits {{/if}}
      - CS {{this.id}}
      {{/forEach}}
      {{#forEach this.workitems}}
      {{#if isFirst}}### Workitems {{/if}}
      - WI {{this.id}}
      {{/forEach}}
      {{#forEach this.tests}}
      {{#if isFirst}}### Tests {{/if}}
      - Test {{this.id}}
        -  Name: {{this.testCase.name}}
        -  Outcome: {{this.outcome}}
      {{/forEach}}
      {{/forEach}}

      # Global list of WI ({{workItems.length}})
      {{#forEach this.workItems}}
      {{#if isFirst}}### WorkItems {{/if}}
      *  **{{this.id}}**  {{lookup this.fields 'System.Title'}}
        - **WIT** {{lookup this.fields 'System.WorkItemType'}}
        - **Tags** {{lookup this.fields 'System.Tags'}}
        - **Assigned** {{#with (lookup this.fields 'System.AssignedTo')}} {{displayName}} {{/with}}
        - **Description** {{{lookup this.fields 'System.Description'}}}
        - **Parents**
      {{#forEach this.relations}}
      {{#if (contains this.attributes.name 'Parent')}}
      {{#with (lookup_a_work_item ../../relatedWorkItems  this.url)}}
            - {{this.id}} - {{lookup this.fields 'System.Title'}}
      {{/with}}
      {{/if}}
      {{/forEach}}
        - **Children**
      {{#forEach this.relations}}
      {{#if (contains this.attributes.name 'Child')}}
      {{#with (lookup_a_work_item ../../relatedWorkItems  this.url)}}
            - {{this.id}} - {{lookup this.fields 'System.Title'}}
      {{/with}}
      {{/if}}
      {{/forEach}}
      {{/forEach}}

      # Global list of CS ({{commits.length}})
      {{#forEach commits}}
      {{#if isFirst}}### Associated commits{{/if}}
      * **ID{{this.id}}**
        -  **Message:** {{this.message}}
        -  **Commited by:** {{this.author.displayName}}
        -  **FileCount:** {{this.changes.length}}
      {{#forEach this.changes}}
            -  **File path (TFVC or TfsGit):** {{this.item.path}}  
      {{/forEach}}
      {{/forEach}}
    checkStage: false
    overrideStageName: 'dev'
    stopOnRedeploy: false
    sortWi: true
    dumpPayloadToConsole: false
    dumpPayloadToFile: false
    replaceFile: true
    getParentsAndChildren: true

Example Template

The example template used is simply the example template from the extension iteself. It adds linked Work items, Pull Requests and Commits.

WIKI Updater Tasks

So after the first step, we do now have a fancy markdown file. Our story could end here, as you don't have to shed single tear anymore, BUT we want ALL THE AZURE DEV OPS MAGIC! So let us automatically deploy the generated markdownfile to a github or azure dev ops wiki.

You need to install WIKI Updater Tasks, which is also from Richard Fennel, thanks dude!

This plugin simply takes the markdown file and pushes it to a git repo.
So add a Git Based Single File Updater as we only generate a single file. If you deploy to a github wiki, like in our example, you need to generate a PAT. Now you can specify a gitname and gitemail, the user and email adress does not need to exist, like in our case. You can also use Azure DevOps variables to insert the Maintainer, who triggered the release/build.

Specify the sourceFile, which is the file we created in the first step.

sourceFile: '$(System.DefaultWorkingDirectory)\releasenotes.md'

You can specify the commit message.

message: 'Update Documentation'

Specify the filename in the remote repository

filename: 'releasenotes.md'

We don't want to replace the file.

replaceFile: false

Instead we want to append to the file.

appendToFile: True

I created a secret variable in the build pipeline and named it github-passwort, that is the PAT.

password: '$(github-passwort)'

The user i created the PAT for was Nerzal.

user: 'Nerzal'

Exmaple Configuration


1
2
3
4
5
6
7
8
9
10
11
12
13
14
- task: WikiUpdaterTask@1
  inputs:
    repo: 'https://github.com/Clarilab/kycnow-changelog.git'
    filename: 'releasenotes.md'
    replaceFile: false
    appendToFile: True
    dataIsFile: true
    sourceFile: '$(System.DefaultWorkingDirectory)\releasenotes.md'
    message: 'Update Documentation'
    gitname: 'clarilab-bot'
    gitemail: 'bot@clarilab.de'
    user: 'Nerzal'
    password: '$(github-passwort)'
    localpath: '$(System.DefaultWorkingDirectory)\repo'

Wiki for both extensions

You can find the wiki for both extensions. here

Result Example

image

Where to go from here?

Now as we do automatically create and deploy a changelog on each build, we might want to adjust the handlebar template to customize our changelog.
As soon as i have a better understanding of these templates, i will write another blog post with more detail in templating.

This blog post is brought to u by my new fancy markdown plugin

ttheel

%d Bloggern gefällt das:

Durch die weitere Nutzung der Seite stimmst du der Verwendung von Cookies zu. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklären Sie sich damit einverstanden.

Schließen