{"id":11143,"date":"2024-08-06T20:44:00","date_gmt":"2024-08-07T01:44:00","guid":{"rendered":"https:\/\/www.rushworth.us\/lisa\/?p=11143"},"modified":"2024-09-06T10:52:37","modified_gmt":"2024-09-06T15:52:37","slug":"using-templates-in-azure-build-pipelines","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=11143","title":{"rendered":"Using Templates in Azure Build Pipelines"},"content":{"rendered":"\n<p>I inherited a Java application that is actually <em>five<\/em> applications &#8212; and the build pipeline had a <em>lot<\/em> of repetition. Tell maven to use <em>this<\/em> POM file, now use <em>that<\/em> one, and now the <em>other<\/em> one. It wasn&#8217;t great, but it got even more cumbersome when I needed to split the production and development builds to use a different pool (network rule: prod and dev servers may not communicate &#8230; so the dev agent talks to the dev image repo which is used by the dev deployment. The prod agent talks to the <em>prod<\/em> image repo which is used by the prod deployment). Instead of having five &#8220;hey, maven, do this build&#8221; blocks, I now have <em>ten<\/em>.<\/p>\n\n\n\n<p>So I created a template for the build step &#8212; jdk-path and maven-path are pipeline variables.  The rest is the Maven build task with parameters to supply the step display name, pom file to use, and environment flag. <\/p>\n\n\n\n<p><strong>Maven Build Template:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\n# maven-build-step.yml\nparameters:\n  - name: pomFile\n    type: string\n  - name: dockerEnv\n    type: string\n  - name: displayName\n    type: string\n\nsteps:\n  - task: Maven@3\n    displayName: &#039;${{ parameters.displayName }}&#039;\n    inputs:\n      mavenPomFile: &#039;${{ parameters.pomFile }}&#039;\n      mavenOptions: &#039;-Xmx3072m&#039;\n      javaHomeOption: &#039;Path&#039;\n      jdkDirectory: $(jdk-path)\n      mavenVersionOption: &#039;Path&#039;\n      mavenDirectory: $(maven-path)\n      mavenSetM2Home: true\n      jdkArchitectureOption: &#039;x64&#039;\n      publishJUnitResults: true\n      testResultsFiles: &#039;**\/surefire-reports\/TEST-*.xml&#039;\n      goals: &#039;package -Denv=${{ parameters.dockerEnv }} jib:build&#039;\n<\/pre><\/div>\n\n\n<p>Then my build pipeline uses the template and supplies a few parameters<\/p>\n\n\n\n<p><strong>Pipeline:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: yaml; title: ; notranslate\" title=\"\">\n# azure-pipelines.yml\ntrigger: none\n\nvariables:\n  appName: &#039;NPM&#039;\n\nstages:\n  - stage: Build\n    jobs:\n      - job: NonProdBuild\n        condition: ne(variables&#x5B;&#039;Build.SourceBranchName&#039;], &#039;production&#039;)\n        displayName: &#039;Build non-production branch&#039;\n        variables:\n          DockerFlag: &#039;docker_dev&#039;\n        pool:\n          name: &#039;Engineering NPM&#039;\n        steps:\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/KafkaStreamsApp\/npm\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Kafka Streams App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/DataSync\/npmInfo\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Data Sync App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/GroupingRules\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Grouping Rules App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/Errorhandler\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Error Handler App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/Events\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Events App&#039;\n\n      - job: ProdBuild\n        condition: eq(variables&#x5B;&#039;Build.SourceBranchName&#039;], &#039;production&#039;)\n        displayName: &#039;Build production branch&#039;\n        variables:\n          DockerFlag: &#039;docker_prod&#039;\n        pool:\n          name: &#039;Engineering NPM Prod&#039;\n        steps:\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/KafkaStreamsApp\/npm\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Kafka Streams App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/DataSync\/npmInfo\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Data Sync App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/GroupingRules\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Grouping Rules App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/Errorhandler\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Error Handler App&#039;\n\n          - template: maven-build-template.yml\n            parameters:\n              pomFile: &#039;JAVA\/Events\/pom.xml&#039;\n              dockerEnv: $(DockerFlag)\n              displayName: &#039;Building Events App&#039;\n<\/pre><\/div>\n\n\n<p>I think this could be made more concise &#8230; but it will do for now!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I inherited a Java application that is actually five applications &#8212; and the build pipeline had a lot of repetition. Tell maven to use this POM file, now use that one, and now the other one. It wasn&#8217;t great, but it got even more cumbersome when I needed to split the production and development builds &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1510],"tags":[1091,2047,2048,1092,2045,2046],"class_list":["post-11143","post","type-post","status-publish","format-standard","hentry","category-ado","tag-ado","tag-azure-build-pipeline","tag-azure-build-pipelines","tag-azure-devops","tag-azure-pipeline","tag-azure-pipelines"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/11143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11143"}],"version-history":[{"count":1,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/11143\/revisions"}],"predecessor-version":[{"id":11144,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/11143\/revisions\/11144"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}