├── .gitignore ├── .order ├── LICENSE ├── README.md ├── assets ├── docker │ └── aspnet.dockerfile └── kubernetes │ ├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ └── service.yaml │ └── overlays │ ├── cpuLimits.yaml │ ├── kustomization.yaml │ └── replicas.yaml ├── docs ├── .order ├── presets │ ├── jobTypes.md │ └── stepLists.md ├── stages.md └── steps │ ├── build.md │ ├── build │ ├── containerImage.md │ ├── dotNetCore.md │ ├── helmTemplate.md │ └── nugetPackage.md │ ├── code.md │ ├── code │ ├── dotNetTests.md │ └── sonarQube.md │ ├── deploy.md │ ├── deploy │ ├── armTemplate.md │ ├── helmChart.md │ ├── helmManifest.md │ ├── kubeManifest.md │ └── terraformTemplate.md │ ├── test.md │ └── test │ └── visualStudioTest.md ├── jobs ├── build.yaml └── deployment.yaml ├── pipelines ├── jobTypes-dockerBuild.yaml └── stepLists-testScripts.yaml ├── presets ├── jobTypes.yaml ├── multiStage.yaml └── stepLists.yaml ├── stages.yaml └── steps ├── build ├── containerImage.yaml ├── dotNetCore.yaml ├── helmTemplate.yaml └── nugetPackage.yaml ├── code ├── dotNetTests.yaml └── sonarQube.yaml ├── deploy ├── armTemplate.yaml ├── helmChart.yaml ├── helmManifest.yaml ├── kubeManifest.yaml └── terraformTemplate.yaml ├── postSteps.yaml ├── preSteps.yaml └── test └── visualStudioTest.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/settings.json 2 | -------------------------------------------------------------------------------- /.order: -------------------------------------------------------------------------------- 1 | README 2 | docs -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /assets/docker/aspnet.dockerfile: -------------------------------------------------------------------------------- 1 | ARG registry=mcr.microsoft.com 2 | ARG repository=dotnet/aspnet 3 | ARG tag=3.1-focal 4 | ARG copy=. 5 | ARG entrypoint=app.dll 6 | FROM ${registry}/${repository}:${tag} 7 | ENV entrypoint=${entrypoint} 8 | EXPOSE 80 9 | EXPOSE 443 10 | USER 9000 11 | WORKDIR /app 12 | COPY ${copy} . 13 | ENTRYPOINT ["dotnet", "${entrypoint}"] -------------------------------------------------------------------------------- /assets/kubernetes/base/deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: '#{KubeComponentName}#' 6 | namespace: '#{namespace}#' 7 | spec: 8 | selector: 9 | matchLabels: 10 | app: '#{KubeComponentName}#' 11 | replicas: 1 12 | template: 13 | metadata: 14 | labels: 15 | app: '#{KubeComponentName}#' 16 | spec: 17 | containers: 18 | - name: '#{KubeComponentName}#' 19 | image: '#{ImageRegistry}#/#{ImageRepository}#:#{ImageTag}#' 20 | resources: 21 | requests: 22 | memory: "256Mi" 23 | cpu: "100m" 24 | limits: 25 | memory: "4096Mi" 26 | cpu: "1000m" 27 | ports: 28 | - containerPort: 443 29 | volumeMounts: 30 | - name: config-volume 31 | mountPath: /app/config 32 | volumes: 33 | - name: config-volume 34 | configMap: 35 | name: '#{KubeComponentName}#-configmap' 36 | -------------------------------------------------------------------------------- /assets/kubernetes/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.config.k8s.io/v1beta1 3 | kind: Kustomization 4 | 5 | commonLabels: 6 | app: '#{KubeComponentName}#' 7 | 8 | resources: 9 | - deployment.yaml 10 | - service.yaml 11 | 12 | namespace: '#{namespace}#' -------------------------------------------------------------------------------- /assets/kubernetes/base/service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: '#{KubeComponentName}#' 6 | spec: 7 | ports: 8 | - port: 443 9 | selector: 10 | app: '#{KubeComponentName}#' -------------------------------------------------------------------------------- /assets/kubernetes/overlays/cpuLimits.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: '#{KubeComponentName}#' 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: '#{KubeComponentName}#' 10 | template: 11 | spec: 12 | containers: 13 | - name: '#{KubeComponentName}#' 14 | resources: 15 | requests: 16 | memory: "256Mi" 17 | cpu: "100m" 18 | limits: 19 | memory: "4096Mi" 20 | cpu: "1000m" -------------------------------------------------------------------------------- /assets/kubernetes/overlays/kustomization.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kustomize.config.k8s.io/v1beta1 3 | kind: Kustomization 4 | 5 | commonLabels: 6 | app: '#{KubeComponentName}#' 7 | env: dev 8 | 9 | bases: 10 | - ../../base 11 | 12 | namespace: '#{namespace}#' 13 | 14 | patches: 15 | - path: replicas.yaml 16 | - path: cpuLimits.yaml -------------------------------------------------------------------------------- /assets/kubernetes/overlays/replicas.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: '#{KubeComponentName}#' 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: '#{KubeComponentName}#' 10 | replicas: 1 11 | template: 12 | spec: 13 | containers: 14 | - name: '#{KubeComponentName}#' -------------------------------------------------------------------------------- /docs/.order: -------------------------------------------------------------------------------- 1 | pipeline 2 | build 3 | deploy -------------------------------------------------------------------------------- /docs/presets/stepLists.md: -------------------------------------------------------------------------------- 1 | # Azure Pipeline Templates 2 | 3 | - [Azure Pipeline Templates](#azure-pipeline-templates) 4 | - [Template Parameter Schema](#template-parameter-schema) 5 | 6 | ## Template Parameter Schema 7 | 8 | To use the pipeline templates in this repository it must be listed as a resource in your pipeline YAML file. This allows you to reference paths in another repository by using the resource identifier. 9 | 10 | ```yaml 11 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 12 | 13 | resources: 14 | repositories: 15 | - repository: templates # Resource identifier for template usage 16 | type: github 17 | name: fitchtech/AzurePipelines # This repository 18 | ref: refs/tags/v1 # The tagged release of the repository 19 | endpoint: GitHub # Azure Service Connection Name 20 | 21 | trigger: 22 | branches: 23 | include: 24 | - master # CI Trigger on commit to master 25 | tags: 26 | include: 27 | - v*.*.*-* # CI Trigger when tag matches format 28 | 29 | extends: 30 | # file path to the template at repo resource id to extend from 31 | template: presets/stepLists.yaml@templates 32 | parameters: 33 | # code: stage in stages 34 | # job: codeSteps 35 | codeSteps: 36 | - script: echo insert steps into stepList for codeSteps job 37 | # job: codeTemplate 38 | codeTemplate: dotNetTests # code steps template name: dotNetTests | sonarQube | false (default) | i.e. ../steps/code/${{ parameters.codeTemplate }}.yaml 39 | # If codeTemplate, codeParameters are the parameters for the codeTemplate 40 | codeParameters: 41 | tests: 42 | - projects: '***[Uu]nit.[Tt]est*.csproj' # Pattern search for unit test projects 43 | arguments: '--collect "Code Coverage" /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Common.TestResultsDirectory)\Coverage\' 44 | displayName: 'dotNet Unit Tests' 45 | testRunTitle: 'Unit Tests' # Optional, if task displayName is different than testRunTitle 46 | codeMatrix: '' 47 | codeMaxParallel: 2 48 | codeVariables: '' 49 | codeJobs: [] 50 | codePool: 51 | vmImage: 'windows-latest' 52 | # build: stage in stages 53 | # job: buildSteps 54 | buildSteps: 55 | - script: echo insert steps into stepList for codeSteps job 56 | # job: buildTemplate 57 | buildTemplate: containerImage # build steps template name: containerImage | dotNetCore | helmTemplate | nugetPackage | false (default) | i.e. ../steps/build/${{ parameters.buildTemplate }}.yaml 58 | buildParameters: 59 | dockerFile: $(dockerfile) 60 | containerRepository: $(repository) 61 | containerRegistry: 'serviceConnectionName' 62 | buildMatrix: 63 | containerImage1: 64 | dockerfile: 'app1.dockerfile' 65 | repository: 'app1' 66 | containerImage2: 67 | dockerfile: 'app2.dockerfile' 68 | repository: 'app2' 69 | buildMaxParallel: 2 70 | buildVariables: '' 71 | buildJobs: [] 72 | buildPool: 73 | vmImage: 'ubuntu-18.04' 74 | 75 | # deploy: stage in stages 76 | 77 | ``` 78 | -------------------------------------------------------------------------------- /docs/stages.md: -------------------------------------------------------------------------------- 1 | # Azure Pipeline Multistage Template 2 | 3 | - [Azure Pipeline Multistage Template](#azure-pipeline-multistage-template) 4 | - [Stages Template Usage](#stages-template-usage) 5 | - [Stages Template Parameters](#stages-template-parameters) 6 | - [Stages Template Syntax](#stages-template-syntax) 7 | 8 | ## Stages Template Usage 9 | 10 | The [stages](../stages.yaml) template encapsulates stages for a multistage pipeline that uses expressions to conditionally insert each stage and dependency if the stage has jobs listed. This template abstracts the stages and jobs within each stage. 11 | 12 | - Validates the syntax of jobs and deployments in each stage 13 | - Inserts each stage defined in the 'stages' parameters into the stages: section only if the stage has jobs 14 | - Dependencies for each stage in stages are only inserted when the dependent stage has jobs 15 | - Predefines all the common stages, their dependencies, and conditions, in a multistage pipeline 16 | - Allows you to insert steps template into the job of a stage 17 | - Orders the stages section according to how they are listed in the stages parameter 18 | 19 | ## Stages Template Parameters 20 | 21 | Insert jobs into a stage by using the jobList or deploymentList parameter with the same name as the stage in the stages parameter 22 | 23 | - **code:** jobList of static code analysis jobs. Conditionally run when triggered by Pull Request (PR) or manual execution 24 | - **build:** jobList of build jobs. For example, dotNet build, docker build, etc. 25 | - **deploy:** deploymentList of deployment jobs. For example, deploy ARM Template, deploy Kubernetes manifest, etc. 26 | - **test:** jobList of test jobs to run after deploy stage. For example, after deploying canary run Visual Studio Test job for functional test of the deployment 27 | - **promote:** deploymentList of deployment jobs, dependent on deploy and test stages, to promote the deployment in or to an environment. For example, with a canary strategy, promote the canary in deploy stage to baseline if successfully running 28 | - **reject:** deploymentList of deployment jobs, dependent on deploy, test, and promote if the stage has jobs and a stage failed. Jobs to reject a failed deployment, to automatically deleted resources that are not functioning 29 | 30 | To use the jobList and deploymentList parameters above the stage name in the stages parameter must match the jobList or deploymentList parameter name. The stages parameter can be used to modify the order or stages, their dependencies, conditions, add or delete stages. 31 | 32 | - **stages:** default: code, build, deploy, test, promote, and reject stages 33 | - Optional parameter to override the stageList default to add stages or update the dependencies or conditions of predefined stages 34 | - **stagesPrefix:** or **stagesSuffix:** parameters to optionally add a prefix or suffix respectively to the name of all stages 35 | - stagesSuffix: Dev would make stages named buildDev, deployDev, etc. 36 | - stagesPrefix: 'dev-' would make stages named dev-build, dev-deploy, etc. 37 | - **stagesCondition:** parameter to optionally override the condition of all stages within the stages stageList 38 | 39 | ## Stages Template Syntax 40 | 41 | To use the [stages](../stages.yaml) template in this repository the pipeline YAML file in your repository must include a resource named templates referencing this AzurePipelines repository. This allows you to reference paths in the repository resource by using the resource identifier. 42 | 43 | The following shows extending from the stages template directly with its parameters. 44 | 45 | ```yaml 46 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 47 | 48 | resources: 49 | repositories: 50 | - repository: templates # Resource identifier for template usage 51 | type: github 52 | name: fitchtech/AzurePipelines # This repository 53 | ref: refs/tags/v1 # The tagged release of the repository 54 | endpoint: GitHub # Azure Service Connection Name 55 | 56 | trigger: 57 | branches: 58 | include: 59 | - master # CI Trigger on commit to master 60 | tags: 61 | include: 62 | - v*.*.*-* # CI Trigger when tag matches format 63 | 64 | extends: 65 | # file path to template at repo resource id to extend from 66 | template: stages.yaml@templates 67 | parameters: 68 | code: [] # jobList inserted into code stage in stages param 69 | build: [] # jobList inserted into build stage in stages param 70 | deploy: [] # deploymentList inserted into deploy stage in stages param 71 | test: [] # jobList inserted into test stage in stages param 72 | promote: [] # deploymentList inserted into promote stage in stages param 73 | reject: [] # deploymentList inserted into reject stage in stages param 74 | # The jobList and deploymentList above are inserted into the stage in stages matching the parameter name 75 | # stages: [] # Optional to override default of stages stageList. 76 | stagesPrefix: '' # Optional stage name prefix. e.g. dev- would make dev-build, dev-deploy, etc. 77 | stagesSuffix: '' # Optional stage name suffix. e.g. Dev would make buildDev, deployDev, etc. 78 | stagesCondition: '' # Optional param to override the condition of all stages 79 | ``` 80 | 81 | When creating a pipeline template that nests the stages template it is inserted into the stages: section instead of extending from it. 82 | 83 | ```yaml 84 | parameters: 85 | # code: stage 86 | - name: codeSteps # stepList inserted into code stage in stages 87 | type: stepList 88 | default: [] 89 | - name: codePool # Nested into pool param of code jobs 90 | type: object 91 | default: 92 | vmImage: 'windows-latest' 93 | # build: stage 94 | - name: buildSteps # stepList inserted into build job 95 | type: stepList 96 | default: [] 97 | - name: buildPool # Nested into pool param of build jobs 98 | type: object 99 | default: 100 | vmImage: 'Ubuntu-16.04' 101 | # deploy: stage 102 | - name: preDeploySteps # Deployment job preDeploy lifecycle hook 103 | type: stepList 104 | default: [] 105 | - name: deploySteps # stepList inserted into deploy job 106 | type: stepList 107 | default: [] 108 | - name: routeTrafficSteps # Deployment job routeTraffic lifecycle hook 109 | type: stepList 110 | default: [] 111 | - name: postRouteTrafficSteps # Deployment job postRouteTraffic lifecycle hook 112 | type: stepList 113 | default: [] 114 | - name: onFailureSteps # Deployment job on: failure: lifecycle hook 115 | type: stepList 116 | default: [] 117 | - name: onSuccessSteps # Deployment job on: success: lifecycle hook 118 | type: stepList 119 | default: [] 120 | - name: deployPool # Nested into pool param of deploy, promote, and reject jobs 121 | type: object 122 | default: 123 | vmImage: 'ubuntu-18.04' 124 | - name: strategy 125 | type: string 126 | default: runOnce 127 | values: 128 | - runOnce 129 | - canary 130 | - rolling 131 | # test: stage 132 | - name: testSteps # stepList inserted into test job 133 | type: stepList 134 | default: [] 135 | - name: testPool # Nested into pool param of test jobs 136 | type: object 137 | default: 138 | vmImage: 'windows-latest' 139 | # promote: stage 140 | - name: promoteSteps # stepList inserted into promote job 141 | type: stepList 142 | default: [] 143 | # reject: stage 144 | - name: rejectSteps # stepList inserted into reject job 145 | type: stepList 146 | default: [] 147 | # overrides 148 | - name: stages # Optional to override the default value of stages stageList in the stages.yaml template 149 | type: stageList 150 | default: '' 151 | - name: stagesSuffix # Optional stage name suffix. e.g. Dev would make buildDev, deployDev, etc. 152 | type: string 153 | default: '' 154 | - name: stagesPrefix # Optional stage name prefix. e.g. dev- would make dev-build, dev-deploy, etc. 155 | type: string 156 | default: '' 157 | - name: stagesCondition # Optional param to override the condition of all stages 158 | type: string 159 | default: '' 160 | 161 | stages: 162 | - template: stages.yaml 163 | # parameters: within stages.yaml 164 | parameters: 165 | # if steps in codeSteps, insert the code job 166 | ${{ if gt(length(parameters.codeSteps), 0) }}: 167 | code: 168 | - job: code1 # job name must be unique within stage 169 | displayName: 'Code Job' # job display name 170 | pool: ${{ parameters.codePool }} # param passed to pool of code jobs 171 | steps: 172 | - ${{ parameters.codeSteps }} 173 | # if steps in buildSteps, insert the build job 174 | ${{ if gt(length(parameters.buildSteps), 0) }}: 175 | build: 176 | - job: build1 # job name must be unique within stage 177 | displayName: 'Build Job' # job display name 178 | pool: ${{ parameters.buildPool }} # param passed to pool of build jobs 179 | steps: 180 | - ${{ parameters.buildSteps }} 181 | # if steps in deploySteps, insert the deploy job 182 | ${{ if gt(length(parameters.deploySteps), 0) }}: 183 | deploy: 184 | - deployment: deploy1 # deployment name unique to stage 185 | displayName: 'Deployment Job' 186 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 187 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 188 | strategy: 189 | ${{ parameters.strategy }}: 190 | # Insert preDeploy lifecycle hook stepList 191 | ${{ if gt(length(parameters.preDeploy), 0) }}: 192 | preDeploy: 193 | pool: ${{ parameters.deployPool }} 194 | steps: 195 | - ${{ parameters.preDeploy }} 196 | # Insert deploySteps stepList 197 | deploy: 198 | steps: 199 | - ${{ parameters.deploySteps }} 200 | # routeTraffic lifecycle hook 201 | ${{ if gt(length(parameters.routeTrafficSteps), 0) }}: 202 | routeTraffic: 203 | pool: ${{ parameters.deployPool }} 204 | steps: 205 | - ${{ parameters.routeTrafficSteps }} 206 | # postRouteTraffic lifecycle hook 207 | ${{ if gt(length(parameters.postRouteTrafficSteps), 0) }}: 208 | postRouteTraffic: 209 | pool: ${{ parameters.deployPool }} 210 | steps: 211 | - ${{ parameters.postRouteTraffic }} 212 | # on: failure: and success: lifecycle hooks 213 | ${{ if or(gt(length(parameters.onFailureSteps), 0), gt(length(parameters.onSuccessSteps), 0)) }}: 214 | on: 215 | ${{ if gt(length(parameters.onSuccessSteps), 0) }}: 216 | # Insert onSuccess stepList 217 | success: 218 | pool: ${{ parameters.deployPool }} 219 | steps: 220 | - ${{ parameters.parameters.onSuccessSteps }} 221 | # Insert onFailure stepList 222 | ${{ if gt(length(parameters.onFailureSteps), 0) }}: 223 | failure: 224 | pool: ${{ parameters.deployPool }} 225 | steps: 226 | - ${{ parameters.onFailureSteps }} 227 | # if steps in testSteps, insert the test job 228 | ${{ if gt(length(parameters.testSteps), 0) }}: 229 | test: 230 | - job: test1 # job name must be unique within stage 231 | displayName: 'Test Job' # job display name 232 | pool: ${{ parameters.testPool }} # param passed to pool of test jobs 233 | steps: 234 | - ${{ parameters.testSteps }} 235 | # if steps in promoteSteps, insert the promote job 236 | ${{ if gt(length(parameters.promoteSteps), 0) }}: 237 | promote: 238 | - deployment: promote1 # deployment name unique to stage 239 | displayName: 'Promote Deployment Job' 240 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 241 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 242 | strategy: 243 | runOnce: 244 | deploy: 245 | steps: 246 | - ${{ parameters.promoteSteps }} 247 | # if steps in rejectSteps, insert the reject job 248 | ${{ if gt(length(parameters.rejectSteps), 0) }}: 249 | reject: 250 | - deployment: reject1 # deployment name unique to stage 251 | displayName: 'Reject Deployment Job' 252 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 253 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 254 | strategy: 255 | runOnce: 256 | deploy: 257 | steps: 258 | - ${{ parameters.rejectSteps }} 259 | ${{ if gt(length(parameters.stages), 0) }}: 260 | # If stages stageList param has value then override default stages value in stages.yaml template 261 | stages: ${{ parameters.stages }} 262 | # These parameters are nested from the parameters section above 263 | stagesSuffix: ${{ parameters.stagesSuffix }} 264 | stagesPrefix: ${{ parameters.stagesPrefix }} 265 | stagesCondition: ${{ parameters.stagesCondition }} 266 | ``` 267 | -------------------------------------------------------------------------------- /docs/steps/build.md: -------------------------------------------------------------------------------- 1 | # Build Job Documentation 2 | 3 | | Documentation | Description | 4 | | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | 5 | | [Build Container Image](./build/containerImage.md) | Build and push a docker image using an optional dotNet solution and dockerfile | 6 | | [Render Helm Charts and Publish Manifests Artifact](./build/helmTemplate.md) | Render Helm Charts with Helm Template cmd and deploy manifests to Kubernetes | 7 | | [Build dotNet Project and Publish Artifact](./build/dotNetCore.md) | Build and publish a dotNet project without any tests | 8 | | [Pack and Push Nuget Package](./build/nugetPackage.md) | A wrapper for the [dotNetCore](./build/dotNetCore.md) steps template with parameterized defaults for pack and push of Nuget Packages to a Azure or external feed | 9 | -------------------------------------------------------------------------------- /docs/steps/build/containerImage.md: -------------------------------------------------------------------------------- 1 | # Build Container Image Steps Template 2 | 3 | - [Build Container Image Steps Template](#build-container-image-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | - [Direct Steps Template Usage](#direct-steps-template-usage) 7 | 8 | ## Steps Template Usage 9 | 10 | - You can add multiple Container Image build jobs into a jobLists so long as the job name is unique within the stage 11 | - This template nests the [dotNetCore](dotNetCore.md) steps template to dotNet publish a project before docker build so that the publish output can be copied from the build agent into the container image. 12 | 13 | ## Insert Steps Template into Stages Template 14 | 15 | The following example shows how to insert the containerImage steps template into the [stages](../../stages.md) template with the minimum required params. This shows one containerImage job added to the build stage jobLists. Additionally, you can add as many build jobs as needed. This example has no deployments. However, it is recommended that you could create a single multistage pipeline that includes code, build, deploy, test, and promote stages in a single pipeline. 16 | 17 | Alternatively, you could create a separate deployment pipeline that triggers on the completion of a build pipeline. This pattern could be used to create a build pipeline decoupled from deployments. To do this would require a pipeline resource trigger added into the resources in your deployment pipeline. The resource in your deployment pipeline would be the build pipeline as a source. When the build pipeline completes if the source pipeline triggers match then the deployment pipeline would run. 18 | 19 | ```yml 20 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 21 | 22 | parameters: 23 | # params to pass into stages.yaml template: 24 | - name: buildPool # Nested into pool param of build jobs 25 | type: object 26 | default: 27 | vmImage: 'Ubuntu-16.04' 28 | - name: dotNetProjects # Required param to restore and publish a dotNet project 29 | type: string 30 | default: '**.csproj' # path or pattern match of projects to dotNet publish 31 | - name: dockerFile # Nested into dockerFile of build jobs 32 | type: string 33 | default: '**.dockerfile' # path to dockerfile for docker build task 34 | - name: dockerArgs # Nested into dockerArgs of build jobs 35 | type: string 36 | default: false # optional to add --build-arg in docker build task 37 | - name: dockerTags 38 | type: object 39 | default: $(Build.BuildNumber) 40 | - name: containerRegistry # Nested into containerRegistry param in containerImage job 41 | type: string 42 | default: '' # ADO Service Connection name 43 | - name: containerRepository # repo path in registry 44 | type: string 45 | default: '' 46 | - name: twistlockEnabled # enable twistlock scan task 47 | type: boolean 48 | default: false 49 | - name: twistlockContinue # twistlock vulnerabilities register as a warning instead of an error in the build stage 50 | type: boolean 51 | default: false 52 | 53 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 54 | 55 | resources: 56 | repositories: 57 | - repository: templates # Resource identifier for template usage 58 | type: github 59 | name: fitchtech/AzurePipelines # This repository 60 | ref: refs/tags/v1 # The tagged release of the repository 61 | endpoint: GitHub # Azure Service Connection Name 62 | 63 | trigger: 64 | branches: 65 | include: 66 | - master # CI Trigger on commit to master 67 | tags: 68 | include: 69 | - v*.*.*-* # CI Trigger when tag matches format 70 | 71 | extends: 72 | # template: file path at repo resource id to extend from 73 | template: stages.yaml@templates 74 | # parameters: within stages.yaml@templates 75 | parameters: 76 | # code: jobList inserted into code stage in stages param 77 | # build: jobList inserted into build stage in stages param 78 | build: 79 | # - if dockerfile, containerRegistry, containerRepository params are not null insert containerImage job into the build stage 80 | - ${{ if and(parameters.dockerFile, parameters.containerRegistry, parameters.containerRepository) }}: 81 | - job: containerImage # job name must be unique within stage 82 | displayName: 'Build Container Image' # job display name 83 | pool: ${{ parameters.buildPool }} # param passed to pool of build jobs 84 | dependsOn: [] # job does not depend on other jobs 85 | # variables: 86 | # key: 'value' # pairs of variables scoped to this job 87 | steps: 88 | # - template: for containerImage steps 89 | - template: steps/build/containerImage.yaml 90 | # parameters within containerImage.yaml template 91 | parameters: 92 | # preSteps: 93 | # - task: add preSteps into job 94 | dotNetProjects: ${{ parameters.dotNetProjects }} 95 | containerRegistry: ${{ parameters.containerRegistry }} 96 | containerRepository: ${{ parameters.containerRepository }} 97 | dockerFile: ${{ parameters.dockerFile }} 98 | dockerTags: ${{ parameters.dockerTags }} 99 | # If dockerArgs is not false 100 | ${{ if parameters.dockerArgs }}: 101 | dockerArgs: ${{ parameters.dockerArgs }} 102 | # If twistlockEnabled is true, insert twistlock scan task 103 | ${{ if parameters.twistlockEnabled }}: 104 | twistlockEnabled: true # enable twistlock scan task 105 | twistlockContinue: ${{ parameters.twistlockContinue }} # twistlock vulnerabilities register as warning instead of error in build stage 106 | # postSteps: 107 | # - task: add postSteps into job 108 | 109 | # - job: insert additional jobs into the build stage 110 | 111 | # deploy: deploymentList inserted into deploy stage in stages param 112 | # promote: deploymentList inserted into promote stage in stages param 113 | # test: jobList inserted into test stage in stages param 114 | # reject: deploymentList inserted into reject stage in stages param 115 | 116 | ``` 117 | 118 | ## Direct Steps Template Usage 119 | 120 | The above example is the recommended pattern for standardizing stages, jobs, and deployments. However, you can use any steps template directly. The below example shows an alternative pattern. 121 | 122 | ```yml 123 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 124 | 125 | parameters: 126 | - name: buildPool # Nested into pool param of build jobs 127 | type: object 128 | default: 129 | vmImage: 'Ubuntu-16.04' 130 | - name: dotNetProjects # Required param to restore and publish a dotNet project 131 | type: string 132 | default: '**.csproj' # path or pattern match of projects to dotNet publish 133 | - name: dockerFile # Nested into dockerFile of build jobs 134 | type: string 135 | default: '**.dockerfile' # path to dockerfile for docker build task 136 | - name: dockerArgs # Nested into dockerArgs of build jobs 137 | type: string 138 | default: '' # optional to add --build-arg in docker build task 139 | - name: containerRegistry # Nested into containerRegistry params in the build job 140 | type: string 141 | default: 'ACR' # ADO Service Connection name 142 | - name: containerRepository # repo path in registry 143 | type: string 144 | default: '' 145 | - name: imageName # containerRepository/imageName nested into containerRepository of containerImage jobs 146 | type: string 147 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 148 | 149 | resources: 150 | repositories: 151 | - repository: templates # Resource identifier for template usage 152 | type: github 153 | name: fitchtech/AzurePipelines # This repository 154 | ref: refs/tags/v1 # The tagged release of the repository 155 | endpoint: GitHub # Azure Service Connection Name 156 | 157 | trigger: 158 | branches: 159 | include: 160 | - master # CI Trigger on commit to master 161 | tags: 162 | include: 163 | - v*.*.*-* # CI Trigger when tag matches format 164 | 165 | stages: 166 | - stage: build 167 | dependsOn: [] 168 | jobs: 169 | - job: containerImage # job name must be unique within stage 170 | displayName: 'Build Container Image' # job display name 171 | pool: ${{ parameters.buildPool }} # param passed to pool of build jobs 172 | dependsOn: [] # job does not depend on other jobs 173 | steps: 174 | - template: steps/build/containerImage.yaml@template # resource identifier required as this is not extending from stages.yaml 175 | parameters: 176 | dotNetProjects: ${{ parameters.dotNetProjects }} 177 | containerRegistry: ${{ parameters.containerRegistry }} 178 | containerRepository: '${{ parameters.containerRepository }}/${{ parameters.imageName }}' 179 | dockerFile: ${{ parameters.dockerFile }} 180 | dockerArgs: ${{ parameters.dockerArgs }} 181 | dockerTags: ${{ parameters.dockerTags }} 182 | 183 | ``` 184 | 185 | It is also valid to omit stages and jobs when you need only one stage and job. You can also hard code values if you do not want the option to override at runtime. 186 | 187 | ```yml 188 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 189 | 190 | pool: 191 | vmImage: 'Ubuntu-16.04' 192 | 193 | resources: 194 | repositories: 195 | - repository: templates # Resource identifier for template usage 196 | type: github 197 | name: fitchtech/AzurePipelines # This repository 198 | ref: refs/tags/v1 # The tagged release of the repository 199 | endpoint: GitHub # Azure Service Connection Name 200 | 201 | steps: 202 | - template: steps/build/containerImage.yaml@template # resource identifier required as this is not extending from stages.yaml 203 | parameters: 204 | dotNetProjects: '**.csproj' 205 | containerRegistry: 'ACR' 206 | containerRepository: 'imageName' 207 | dockerFile: '**.dockerfile' 208 | dockerTags: $(Build.BuildNumber) 209 | 210 | ``` 211 | -------------------------------------------------------------------------------- /docs/steps/build/dotNetCore.md: -------------------------------------------------------------------------------- 1 | # doNetCore Steps Template 2 | 3 | - [doNetCore Steps Template](#donetcore-steps-template) 4 | - [dotNetCore Template Nested](#dotnetcore-template-nested) 5 | - [Steps Template Usage](#steps-template-usage) 6 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 7 | - [Direct Steps Template Usage](#direct-steps-template-usage) 8 | 9 | ## dotNetCore Template Nested 10 | 11 | Like all steps templates, the dotNetCore steps template can be nested in the [stages](../../stages.md) template or directly in steps lists. However, this template is primarily intended to be nested into other steps templates. To provide dotNetCore tasks in other steps templates this template is nested within them. This is so that the common list of steps is not copied from one template to another. 12 | 13 | - The [dotNetTests](./../code/dotNetTests.md) steps template nests the dotNetCore template for dotNet restore tasks 14 | - The [sonarQube](./../code/sonarQube.md) steps template nests the dotNetCore template for dotNet restore and build tasks 15 | - The [containerImage](containerImage.md) steps template nests the dotNetCore template for dotNet publish tasks before the docker build tasks 16 | - The [visualStudioTest](./../test/visualStudioTest.md) steps template nests the dotNetCore template for dotNet build tasks before the Visual Studio Test tasks 17 | 18 | ## Steps Template Usage 19 | 20 | command options are build, publish, and pack: 21 | 22 | - Build a project for code analysis or test jobs. Optional publish pipeline artifact 23 | - Publish a project for container image build. Optional publish pipeline artifact 24 | - Pack project and push Nuget package artifact and symbols to feed 25 | 26 | ## Insert Steps Template into Stages Template 27 | 28 | The following example shows how to insert the dotNetCore steps template into the [stages](../../stages.md) template with the minimum required params. Build a dotNet project and publish a pipeline artifact. This is useful if you want to download the build artifact into other jobs in all stages. 29 | 30 | Note: when using the [dotNetTests](./../code/dotNetTests.md), [sonarQube](../code/sonarQube.md), [containerImage](containerImage.md), or [visualStudioTest](./../test/visualStudioTest.md) templates, using the dotNetCore template directly as shown below would not be needed as it's nested into these templates. 31 | 32 | ```yml 33 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 34 | 35 | parameters: 36 | # params to pass into stages.yaml template: 37 | - name: projects # pattern to match of projects to build, publish, or pack 38 | type: string 39 | default: '**.csproj' 40 | - name: command 41 | type: string 42 | default: build 43 | values: 44 | - build 45 | - publish 46 | - name: buildPool # Nested into pool param of build jobs 47 | type: object 48 | default: 49 | vmImage: 'ubuntu-18.04' 50 | 51 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 52 | 53 | resources: 54 | repositories: 55 | - repository: templates # Resource identifier for template usage 56 | type: github 57 | name: fitchtech/AzurePipelines # This repository 58 | ref: refs/tags/v1 # The tagged release of the repository 59 | endpoint: GitHub # Azure Service Connection Name 60 | 61 | trigger: 62 | branches: 63 | include: 64 | - master # CI Trigger on commit to master 65 | tags: 66 | include: 67 | - v*.*.*-* # CI Trigger when tag matches format 68 | 69 | extends: 70 | # template: file path at repo resource id to extend from 71 | template: stages.yaml@templates 72 | # parameters: within stages.yaml@templates 73 | parameters: 74 | # code: jobList inserted into code stage in stages 75 | # build: jobList inserted into build stage in stages 76 | build: 77 | - job: dotNetBuild # job name must be unique within stage 78 | displayName: 'dotNet Build Projects' # job display name 79 | pool: ${{ parameters.buildPool }} # param passed to pool of build jobs 80 | dependsOn: [] # job does not depend on other jobs 81 | # variables: 82 | # key: 'value' # pairs of variables scoped to this job 83 | steps: 84 | # - template: for dotNetCore steps 85 | - template: steps/build/dotNetCore.yaml 86 | # parameters within dotNetCore.yaml template 87 | parameters: 88 | # preSteps: 89 | # - task: add preSteps into job 90 | command: ${{ parameters.command }} # default in template is build 91 | projects: ${{ parameters.projects }} # pattern to match of projects to build 92 | publishEnabled: true # Set publishEnabled true to publish artifact of dotNet build or publish outputs 93 | # postSteps: 94 | # - task: add postSteps into job 95 | 96 | # - job: insert additional jobs into the build stage 97 | 98 | # deploy: deploymentList inserted into deploy stage in stages param 99 | # promote: deploymentList inserted into promote stage in stages param 100 | # test: jobList inserted into test stage in stages param 101 | # reject: deploymentList inserted into reject stage in stages param 102 | 103 | ``` 104 | 105 | ## Direct Steps Template Usage 106 | 107 | The following example shows inserting a steps template into the steps section. This is to show parameter usage in the template. See the [Insert Steps Templates into Stages Template](#insert-steps-templates-into-stages-template) section above for using this template in the [stages](../../stages.md) template 108 | 109 | ```yml 110 | steps: 111 | # template: insert dotNetCore build and publish pipeline artifact steps into job 112 | - template: steps/build/dotNetCore.yaml 113 | parameters: 114 | # When nesting multiple steps templates into a single job add clean, checkout, and download params set to false. 115 | # checkout: self # preSteps checkout step enabled by default to checkout the source repo 116 | download: false # disables preSteps download steps 117 | preSteps: 118 | - script: echo 'add preSteps stepsList to job' # list of tasks that run before the main steps of the template. Inserted into steps after checkout/download 119 | command: publish # default: build | publish | restore 120 | # packageType: runtime # sdk is the default, only set this to override sdk with runtime 121 | # version: '3.1.x' # UseDotNet@2 version number by default, set to null to skip step 122 | projects: '**.csproj' # pattern match of projects or solution to build or publish 123 | configuration: Release # dotNet configuration flag, e.g. configuration: Release or configuration: Debug 124 | publishEnabled: true # Set publishEnabled true to publish artifact of dotNet build or publish outputs 125 | # feedRestore: '' # Azure DevOps Artifacts Feed 126 | # arguments: '' # Output and no-restore arguments are injected for you. This param is for inserting any additional build/publish args for the task 127 | postSteps: 128 | - script: echo 'add postSteps stepsList to job' # list of tasks that run after the main steps of the template. Inserted into steps before publish/clean 129 | 130 | # template: insert dotNetCore pack and push Nuget artifact steps into job 131 | - template: steps/build/dotNetCore.yaml 132 | parameters: 133 | # When nesting multiple steps templates into a single job add clean, checkout, and download params set to false. 134 | checkout: false # disables preSteps checkout steps 135 | download: false # disables preSteps download steps 136 | preSteps: 137 | - script: echo 'add preSteps stepsList to job' # list of tasks that run before the main steps of the template. Inserted into steps after checkout/download 138 | # packageType: runtime # sdk is the default, only set this to override sdk with runtime 139 | # version: '3.1.x' # UseDotNet@2 version number by default, set to null to skip step 140 | searchPatternPack: '**.csproj' # pattern match of projects or solution to build or publish 141 | searchPatternPush: '$(Build.ArtifactStagingDirectory)/*.nupkg' 142 | includeSymbols: true # dotNet pack include symbols 143 | publishSymbols: true # enable publish symbols task after dotNet pack 144 | configuration: Debug # dotNet configuration flag, e.g. configuration: Release or configuration: Debug 145 | postSteps: 146 | - script: echo 'add postSteps stepsList to job' # list of tasks that run after the main steps of the template. Inserted into steps before publish/clean 147 | 148 | ``` 149 | -------------------------------------------------------------------------------- /docs/steps/build/helmTemplate.md: -------------------------------------------------------------------------------- 1 | # Helm Template Steps Template 2 | 3 | - [Helm Template Steps Template](#helm-template-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | 7 | ## Steps Template Usage 8 | 9 | - The 'helm template' command is used to render Helm charts into Kubernetes Manifests which are published as an artifact 10 | - When using helmTemplate steps in a build job you can publish an artifact of the rendered manifests to later download by a deployment job 11 | 12 | ## Insert Steps Template into Stages Template 13 | 14 | The following example shows how to insert the helmTemplate steps template into the [stages](../../stages.md) template with the minimum required params. 15 | 16 | ```yml 17 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 18 | 19 | parameters: 20 | # params to pass into stages.yaml template: 21 | - name: buildPool # Nested into pool param of build jobs 22 | type: object 23 | default: 24 | vmImage: 'ubuntu-18.04' 25 | - name: namespace 26 | type: string 27 | default: default 28 | - name: helmChartPath # Optional path within Pipeline.Workspace 29 | type: string 30 | default: '' 31 | - name: helmValueFile 32 | type: string 33 | default: 'values.yaml' 34 | 35 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 36 | 37 | resources: 38 | repositories: 39 | - repository: templates # Resource identifier for template usage 40 | type: github 41 | name: fitchtech/AzurePipelines # This repository 42 | ref: refs/tags/v1 # The tagged release of the repository 43 | endpoint: GitHub # Azure Service Connection Name 44 | 45 | trigger: 46 | branches: 47 | include: 48 | - master # CI Trigger on commit to master 49 | tags: 50 | include: 51 | - v*.*.*-* # CI Trigger when tag matches format 52 | 53 | extends: 54 | # template: file path at repo resource id to extend from 55 | template: stages.yaml@templates 56 | # parameters: within stages.yaml@templates 57 | parameters: 58 | # code: jobList inserted into code stage in stages 59 | # build: jobList inserted into build stage in stages 60 | build: 61 | - job: helmTemplate # job name unique to stage 62 | displayName: 'Render Helm Charts' 63 | pool: ${{ parameters.buildPool }} # param passed to pool of deployment jobs 64 | condition: succeeded() 65 | # variables: 66 | # key: 'value' # pairs of variables scoped to this job 67 | dependsOn: [] 68 | steps: 69 | - template: steps/build/helmTemplate.yaml 70 | parameters: 71 | # preSteps: 72 | # - task: add preSteps into job 73 | namespace: ${{ parameters.namespace }} # pass in namespace param 74 | ${{ if parameters.helmChartPath }}: 75 | helmChartPath: '$(Build.Repository.LocalPath)/${{ parameters.helmChartPath }}' # helmChartPath within source checkout root path where charts are located 76 | helmValueFile: '$(Build.Repository.LocalPath)/${{ parameters.helmChartPath }}/${{ parameters.helmValueFile }}' # values file within helmChartPath 77 | ${{ if not(parameters.helmChartPath) }}: 78 | helmChartPath: '$(Build.Repository.LocalPath)' # default source checkout root path 79 | helmValueFile: '$(Build.Repository.LocalPath)/${{ parameters.helmValueFile }}' # values file within helmChartPath 80 | # outputDir: '$(Pipeline.Workspace)/helmTemplate' # This is the default outputDir 81 | # publishEnabled: true # default publish artifact of rendered manifests 82 | # postSteps: 83 | # - task: add postSteps into job 84 | 85 | # - job: insert additional jobs into the build stage 86 | 87 | # deploy: deploymentList inserted into deploy stage in stages param 88 | # promote: deploymentList inserted into promote stage in stages param 89 | # test: jobList inserted into test stage in stages param 90 | # reject: deploymentList inserted into reject stage in stages param 91 | 92 | ``` 93 | -------------------------------------------------------------------------------- /docs/steps/build/nugetPackage.md: -------------------------------------------------------------------------------- 1 | # nugetPackage Steps Template 2 | 3 | - [nugetPackage Steps Template](#nugetpackage-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | 7 | ## Steps Template Usage 8 | 9 | command options are build, publish, and pack: 10 | 11 | - Pack project and push Nuget package artifact and symbols to feed 12 | - Optionally dotNet build or publish a project before dotNet pack and push 13 | 14 | ## Insert Steps Template into Stages Template 15 | 16 | The following example shows how to insert the nugetPackage steps template into the [stages](../../stages.md) template with the minimum required params. 17 | 18 | ```yml 19 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 20 | 21 | parameters: 22 | # params to pass into stages.yaml template: 23 | - name: dotNetPackages # Required to enable pack. Pattern to search for csproj or nuspec files. Separate multiple patterns with semicolon. Exclude patterns with a ! prefix e.g. **/*.csproj;!**/*.Tests.csproj 24 | type: string 25 | default: '**.csproj' 26 | - name: projects # Optional file match pattern to build or publish projects 27 | type: string 28 | default: '**.csproj' 29 | - name: buildPool # Nested into pool param of build jobs 30 | type: object 31 | default: 32 | vmImage: 'ubuntu-18.04' 33 | 34 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 35 | 36 | resources: 37 | repositories: 38 | - repository: templates # Resource identifier for template usage 39 | type: github 40 | name: fitchtech/AzurePipelines # This repository 41 | ref: refs/tags/v1 # The tagged release of the repository 42 | endpoint: GitHub # Azure Service Connection Name 43 | 44 | trigger: 45 | branches: 46 | include: 47 | - master # CI Trigger on commit to master 48 | tags: 49 | include: 50 | - v*.*.*-* # CI Trigger when tag matches format 51 | 52 | extends: 53 | # template: file path at repo resource id to extend from 54 | template: stages.yaml@templates 55 | # parameters: within stages.yaml@templates 56 | parameters: 57 | # code: jobList inserted into code stage in stages 58 | # build: jobList inserted into build stage in stages 59 | build: 60 | - job: dotNetPackage # job name must be unique within stage 61 | displayName: 'dotNet Pack Projects' # job display name 62 | pool: ${{ parameters.buildPool }} # param passed to pool of build jobs 63 | dependsOn: [] # job does not depend on other jobs 64 | variables: 65 | NugetVersion: $[counter(variables['Build.BuildNumber'], 1)] # NugetVersion is the default versionEnvVar (environment variable) used for the versioningScheme dotNet pack for NuGet packages 66 | steps: 67 | # - template: for nugetPackage steps 68 | - template: steps/build/nugetPackage.yaml 69 | # parameters within nugetPackage.yaml template 70 | parameters: 71 | # preSteps: 72 | # - task: add preSteps into job 73 | dotNetPackages: ${{ parameters.dotNetPackages }} # Required pattern to pack and push projects for NuGet Packages 74 | projects: ${{ parameters.projects }} # Optional pattern to restore and build a project before dotNet pack and push 75 | feedRestore: 'projectName/feedName' # for project-scoped feed. FeedName only for organization-scoped feed 76 | feedPublish: 'projectName/feedName' # Push NuGet package to a select feed hosted in your organization. You must have Package Management installed and licensed to select a feed 77 | # command: build # build (default) or publish. This is the command used for projects 78 | publishEnabled: false # Set publishEnabled false to disable artifact publish of dotNet outputDir. It is enabled by default 79 | # postSteps: 80 | # - task: add postSteps into job 81 | 82 | # - job: insert additional jobs into the build stage 83 | 84 | # deploy: deploymentList inserted into deploy stage in stages param 85 | # promote: deploymentList inserted into promote stage in stages param 86 | # test: jobList inserted into test stage in stages param 87 | # reject: deploymentList inserted into reject stage in stages param 88 | 89 | ``` 90 | -------------------------------------------------------------------------------- /docs/steps/code.md: -------------------------------------------------------------------------------- 1 | # Code Job Documentation 2 | 3 | | Documentation | Description | 4 | | --------------------------------------------------------- | ---------------------------------------------------------- | 5 | | [dotNet Test Static Code Analysis](./code/dotNetTests.md) | Run dotNet test projects sequentially with tests parameter | 6 | | [SonarQube Static Code Analysis](./code/sonarQube.md) | Run SonarQube for dotNet projects or solutions | 7 | -------------------------------------------------------------------------------- /docs/steps/code/dotNetTests.md: -------------------------------------------------------------------------------- 1 | # dotNet Test Steps Template 2 | 3 | - [dotNet Test Steps Template](#dotnet-test-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Steps Template Schema](#steps-template-schema) 6 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 7 | - [Direct Steps Template Usage](#direct-steps-template-usage) 8 | 9 | ## Steps Template Usage 10 | 11 | - The 'tests' param within the dotNetTests steps template is a YAML object param that allows you to list multiple dotNet tests projects and arguments 12 | - A dotNet test task is inserted for each item in the tests list parameter 13 | - In the [stages](../../stages.md) Template code jobList param you can add multiple jobs for static code analysis so long as the job name is unique within the stage 14 | 15 | ## Steps Template Schema 16 | 17 | ```yml 18 | steps: 19 | # - template: for code analysis steps 20 | - template: steps/code/dotNetTests.yaml 21 | # parameters: within dotNetTests.yaml template 22 | parameters: 23 | # preSteps: Optional: inserts stepList after checkout and download 24 | preSteps: 25 | - script: echo add stepList of tasks into steps 26 | version: '3.1.x' # Optional: if param has value, use dotNet version task inserted 27 | feedRestore: '' # Optional: GUID of Azure artifact feed. Use when projects restore NuGet artifacts from a private feed 28 | # tests: Required: list of dotNet test tasks that are inserted serially into steps 29 | tests: 30 | # - projects: at least one projects item required at minimum 31 | - projects: '**[Uu]nit.[Tt]est*/*[Uu]nit.[Tt]est*.csproj' # Required: The path to the csproj file(s) to use. You can use wildcards and file matching pattern 32 | arguments: '--collect "Code Coverage" /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Common.TestResultsDirectory)\Coverage\' # Optional: dotNet Test arguments 33 | displayName: 'dotNet Unit Tests' # Optional: Pipeline task display name 34 | # - projects: item for each dotNet test task to be inserted 35 | - projects: '**[Cc][Ll][Ii].[Tt]est*/*[Cc][Ll][Ii].[Tt]est*.csproj' # Pattern search test projects 36 | arguments: '--collect "Code Coverage" /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Common.TestResultsDirectory)\Coverage\' # Optional: dotNet Test arguments 37 | displayName: 'dotNet CLI Tests' # Optional: Pipeline task display name 38 | testRunTitle: 'CLI Test' # Optional: Provides a name for the test run 39 | publishTestResults: false # Optional: default is true. Enabling this option will generate a test results TRX file in $(Agent.TempDirectory) and results will be published 40 | publish: '' # Default: $(Common.TestResultsDirectory) | publish: '' will disable the publish task 41 | publishArtifact: 'artifactName' # Default: $(Build.DefinitionName)_$(System.JobName) 42 | # postSteps: Optional: inserts stepList before publish and clean 43 | postSteps: 44 | - script: echo add stepList of tasks into steps 45 | 46 | ``` 47 | 48 | ## Insert Steps Template into Stages Template 49 | 50 | The following example shows how to insert the dotNetTests steps template into the [stages](../../stages.md) template with the minimum required params. 51 | 52 | ```yml 53 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 54 | 55 | parameters: 56 | # params to pass into stages.yaml template: 57 | - name: codePool 58 | type: object 59 | default: 60 | vmImage: 'windows-latest' # Nested into pool param of code jobs 61 | - name: tests 62 | type: object 63 | default: 64 | - projects: '**[Uu]nit.[Tt]est*/*[Uu]nit.[Tt]est*.csproj' # Pattern search for unit test projects 65 | displayName: 'dotNet Unit Tests' 66 | arguments: '--collect "Code Coverage" /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Common.TestResultsDirectory)\Coverage\' 67 | - projects: '**[Cc][Ll][Ii].[Tt]est*/*[Cc][Ll][Ii].[Tt]est*.csproj' # Pattern search for cli test projects 68 | displayName: 'dotNet CLI Tests' 69 | arguments: '--no-restore --collect "Code Coverage"' 70 | - name: version # Optional dotNet version string to enable use dotNet task 71 | type: string 72 | default: '3.1.x' 73 | 74 | # parameter defaults in the above section can be set on manual run of a pipeline to override 75 | 76 | resources: 77 | repositories: 78 | - repository: templates # Resource identifier for template usage 79 | type: github 80 | name: fitchtech/AzurePipelines # This repository 81 | ref: refs/tags/v1 # The tagged release of the repository 82 | endpoint: GitHub # Azure Service Connection Name 83 | 84 | trigger: 85 | branches: 86 | include: 87 | - master # CI Trigger on commit to master 88 | tags: 89 | include: 90 | - v*.*.*-* # CI Trigger when tag matches format 91 | 92 | extends: 93 | # template: file path at repo resource id to extend from 94 | template: stages.yaml@templates 95 | # parameters: within stages.yaml@templates 96 | parameters: 97 | # code: jobList inserted into code stage in stages 98 | code: 99 | # - job: insert static code analysis jobs into stage 100 | - job: dotNetTests # job name must be unique within stage 101 | displayName: 'dotNet Test Static Code Analysis' # job display name 102 | pool: ${{ parameters.codePool }} # param passed to pool of code jobs 103 | dependsOn: [] # job does not depend on other jobs 104 | # variables: 105 | # key: 'value' # pairs of variables scoped to this job 106 | steps: 107 | # - template: for code analysis steps 108 | - template: steps/code/dotNetTests.yaml 109 | # parameters within dotNetTests.yaml template 110 | parameters: 111 | # preSteps: 112 | # - task: add preSteps into job 113 | tests: ${{ parameters.tests }} 114 | version: ${{ parameters.version }} 115 | # postSteps: 116 | # - task: add postSteps into job 117 | 118 | # - job: insert additional jobs into the code stage 119 | 120 | # build: jobList inserted into build stage in stages param 121 | # deploy: deploymentList inserted into deploy stage in stages param 122 | # promote: deploymentList inserted into promote stage in stages param 123 | # test: jobList inserted into test stage in stages param 124 | # reject: deploymentList inserted into reject stage in stages param 125 | 126 | ``` 127 | 128 | ## Direct Steps Template Usage 129 | 130 | The above example is the recommended pattern for standardizing stages, jobs, and deployments. However, you can use any steps template directly. The below example shows an alternative pattern. 131 | 132 | ```yml 133 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 134 | 135 | parameters: 136 | # params to pass into stages.yaml template: 137 | - name: unitTests # param nested 138 | type: string 139 | default: '**[Uu]nit.[Tt]est*/*[Uu]nit.[Tt]est*.csproj' 140 | - name: cliTests # param nested 141 | type: string 142 | default: '**[Cc][Ll][Ii].[Tt]est*/*[Cc][Ll][Ii].[Tt]est*.csproj' 143 | - name: testArgs 144 | type: string 145 | default: '--collect "Code Coverage" /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Common.TestResultsDirectory)\Coverage\' 146 | - name: codePool 147 | type: object 148 | default: 149 | vmImage: 'windows-latest' # Nested into pool param of code job 150 | 151 | # parameter defaults in the above section can be set on manual run of a pipeline to override 152 | 153 | resources: 154 | repositories: 155 | - repository: templates # Resource identifier for template usage 156 | type: github 157 | name: fitchtech/AzurePipelines # This repository 158 | ref: refs/tags/v1 # The tagged release of the repository 159 | endpoint: GitHub # Azure Service Connection Name 160 | 161 | trigger: 162 | branches: 163 | include: 164 | - master # CI Trigger on commit to master 165 | tags: 166 | include: 167 | - v*.*.*-* # CI Trigger when tag matches format 168 | 169 | stages: 170 | - stage: code 171 | dependsOn: [] 172 | jobs: 173 | - job: dotNetTests # job name must be unique within stage 174 | displayName: 'dotNet Test Static Code Analysis' # job display name 175 | pool: ${{ parameters.codePool }} # param passed to pool of code jobs 176 | dependsOn: [] # job does not depend on other jobs 177 | steps: 178 | - template: steps/code/dotNetTests.yaml@template # resource identifier required as this is not extending from stages.yaml 179 | parameters: 180 | # preSteps: 181 | # - task: add preSteps into job 182 | tests: 183 | - projects: '${{ parametes.unitTests }}' # Pattern search for unit test projects 184 | displayName: 'dotNet Unit Tests' 185 | arguments: '${{ parametes.testArgs }}' 186 | - projects: '${{ parametes.cliTests }}' # Pattern search for cli test projects 187 | displayName: 'dotNet CLI Tests' 188 | arguments: '${{ parametes.testArgs }}' 189 | # postSteps: 190 | # - task: add postSteps into job 191 | # You can customize a list using this pattern 192 | 193 | ``` 194 | -------------------------------------------------------------------------------- /docs/steps/code/sonarQube.md: -------------------------------------------------------------------------------- 1 | # SonarQube Steps Template 2 | 3 | - [SonarQube Steps Template](#sonarqube-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | 7 | ## Steps Template Usage 8 | 9 | - In the [stages](../../stages.md) Template code jobList param you can add multiple jobs for static code analysis so long as the job name is unique within the stage 10 | - The sonarQube steps template provides options for adding SonarQube analysis task in the right order before and after dotNet build of projects 11 | 12 | ## Insert Steps Template into Stages Template 13 | 14 | The following example shows how to insert the sonarQube steps template into the [stages](../../stages.md) template with the minimum required params. 15 | 16 | ```yml 17 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 18 | 19 | parameters: 20 | # params to pass into stages.yaml template: 21 | - name: codePool 22 | type: object 23 | default: 24 | vmImage: 'windows-latest' # Nested into pool param of sonarQube job 25 | # SonarQube Analysis extension for Azure Pipelines 26 | - name: sonarQube # Required sonarQube Service Connection name to insert steps 27 | type: string 28 | default: '' 29 | - name: dotNetProjects # Nested into projects param of sonarQube steps. Can be Visual Studio solution (*.sln) or dotNet projects (*.csproj) to build for SonarQube analysis 30 | type: string 31 | default: '*.sln' 32 | 33 | # parameter defaults in the above section can be set on manual run of a pipeline to override 34 | 35 | resources: 36 | repositories: 37 | - repository: templates # Resource identifier for template usage 38 | type: github 39 | name: fitchtech/AzurePipelines # This repository 40 | ref: refs/tags/v1 # The tagged release of the repository 41 | endpoint: GitHub # Azure Service Connection Name 42 | 43 | trigger: 44 | branches: 45 | include: 46 | - master # CI Trigger on commit to master 47 | tags: 48 | include: 49 | - v*.*.*-* # CI Trigger when tag matches format 50 | 51 | extends: 52 | # template: file path at repo resource id to extend from 53 | template: stages.yaml@templates 54 | # parameters: within stages.yaml@templates 55 | parameters: 56 | # code: jobList inserted into code stage in stages 57 | code: 58 | # - job: insert static code analysis jobs into stage 59 | - job: sonarQube # job name must be unique within stage 60 | displayName: 'SonarQube Static Code Analysis' # job display name 61 | pool: ${{ parameters.codePool }} # param passed to pool of code jobs 62 | dependsOn: [] # job does not depend on other jobs 63 | # variables: 64 | # key: 'value' # pairs of variables scoped to this job 65 | steps: 66 | # - template: for code analysis steps 67 | - template: steps/code/sonarQube.yaml 68 | # parameters within sonarQube.yaml template 69 | parameters: 70 | # preSteps: 71 | # - task: add preSteps into job 72 | sonarQube: ${{ parameters.sonarQube }} 73 | dotNetProjects: ${{ parameters.dotNetProjects }} 74 | # postSteps: 75 | # - task: add postSteps into job 76 | 77 | # - job: insert additional jobs into the code stage 78 | 79 | # build: jobList inserted into build stage in stages param 80 | # deploy: deploymentList inserted into deploy stage in stages param 81 | # promote: deploymentList inserted into promote stage in stages param 82 | # test: jobList inserted into test stage in stages param 83 | # reject: deploymentList inserted into reject stage in stages param 84 | 85 | ``` 86 | -------------------------------------------------------------------------------- /docs/steps/deploy.md: -------------------------------------------------------------------------------- 1 | # Deployment Job Documentation 2 | 3 | | Documentation | Description | 4 | | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | 5 | | [Deploy ARM Templates](./deploy/armTemplate.md) | Deploy an ARM template(s) | 6 | | [Deploy Terraform Templates](./deploy/terraformTemplate.md) | run terraform steps -init, -plan, -validate, -apply, and -destroy with optional command options | 7 | | [Deploy Helm Charts](./deploy/helmChart.md) | Use Helm charts to deploy components to Kubernetes | 8 | | [Render Helm Charts and Deploy Manifests](./deploy/helmManifest.md) | Render Helm Charts with Helm Template cmd and deploy manifests to Kubernetes | 9 | | [Deploy Kubernetes Manifests](./deploy/kubeManifest.md) | Deploy Kubernetes manifests and secrets | 10 | -------------------------------------------------------------------------------- /docs/steps/deploy/armTemplate.md: -------------------------------------------------------------------------------- 1 | # ARM Template Steps Template 2 | 3 | - [ARM Template Steps Template](#arm-template-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Serial Deployment of ARM Templates](#serial-deployment-of-arm-templates) 6 | - [Parallel Deployment of ARM Templates](#parallel-deployment-of-arm-templates) 7 | 8 | ## Steps Template Usage 9 | 10 | - Azure Resource Manager templates (ARM templates) provide Infrastructure as Code (IaC) for Azure. The armTemplate steps template deploys the provided ARM template 11 | - Azure limits ARM deployments to 800 per resource group. This steps template includes an optional cleanup script to remove the oldest deployment so that the limit is not reached which would prevent deployments 12 | 13 | ## Serial Deployment of ARM Templates 14 | 15 | The following example shows how to insert the armTemplate steps template into the [stages](../../stages.md) template with the minimum required params. 16 | 17 | This pattern would deploy each of the templates in the armTemplates list serially within a single job. 18 | 19 | ```yml 20 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 21 | 22 | parameters: 23 | # params to pass into stages.yaml template: 24 | 25 | - name: deployPool # Nested into pool param of deploy jobs 26 | type: object 27 | default: 28 | vmImage: 'ubuntu-18.04' 29 | - name: checkout 30 | type: string 31 | default: self 32 | - name: azureSubscription # Azure Subscription service connection name 33 | type: string 34 | default: '' 35 | - name: resourceGroupName # Azure Resource Group within the subscription 36 | type: string 37 | default: '' 38 | - name: armTemplates 39 | type: object 40 | default: 41 | - template: 'deployment1.json' 42 | parameters: 'parameters1.json' 43 | - template: 'deployment2.json' 44 | parameters: 'parameters2.json' 45 | - name: templatePath # Root path of ARM templates 46 | type: string 47 | default: '$(Build.Repository.LocalPath)' 48 | 49 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 50 | 51 | resources: 52 | repositories: 53 | - repository: templates # Resource identifier for template usage 54 | type: github 55 | name: fitchtech/AzurePipelines # This repository 56 | ref: refs/tags/v1 # The tagged release of the repository 57 | endpoint: GitHub # Azure Service Connection Name 58 | 59 | trigger: 60 | branches: 61 | include: 62 | - master # CI Trigger on commit to master 63 | tags: 64 | include: 65 | - v*.*.*-* # CI Trigger when tag matches format 66 | 67 | extends: 68 | # template: file path at repo resource id to extend from 69 | template: stages.yaml@templates 70 | # parameters: within stages.yaml@templates 71 | parameters: 72 | # code: jobList inserted into code stage in stages 73 | # build: jobList inserted into build stage in stages 74 | # deploy: deploymentList inserted into deploy stage in stages param 75 | deploy: 76 | - deployment: armTemplate # job name unique to stage 77 | displayName: 'Deploy ARM Templates' 78 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 79 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 80 | # variables: 81 | # key: 'value' # pairs of variables scoped to this job 82 | dependsOn: [] 83 | strategy: 84 | runOnce: 85 | deploy: 86 | steps: 87 | - checkout: ${{ parameters.checkout }} 88 | # - for each arm item in armTemplates parameter insert arm deployment steps sequentially 89 | - ${{ each arm in parameters.armTemplates }}: 90 | # - if item in armTemplates parameter has template key 91 | - ${{ if arm.template }}: 92 | - template: steps/deploy/armTemplate.yaml 93 | parameters: 94 | # preSteps: 95 | # - task: add preSteps into job 96 | checkout: false # Disable checkout in preSteps 97 | download: false # Disable download in preSteps 98 | azureSubscription: ${{ parameters.azureSubscription }} # Service connection to subscription for the resource group 99 | resourceGroupName: ${{ parameters.resourceGroupName }} # RM Group name within subscription 100 | templatePath: '${{ parameters.templatePath }}' # root path where ARM templates are located 101 | templateFile: ${{ arm.template }} # ARM template within deploymentDir 102 | ${{ if arm.parameters }}: 103 | parametersFile: ${{ arm.parameters }} # Parameters file within deploymentDir 104 | ${{ if arm.override }}: 105 | overrideParameters: '${{ arm.override }}' # Optionally add args to override values in parameters file 106 | # postSteps: 107 | # - task: add postSteps into job 108 | 109 | # - deployment: insert additional deployment jobs into the deploy stage 110 | 111 | # promote: deploymentList inserted into promote stage in stages param 112 | # test: jobList inserted into test stage in stages param 113 | # reject: deploymentList inserted into reject stage in stages param 114 | 115 | ``` 116 | 117 | ## Parallel Deployment of ARM Templates 118 | 119 | This pattern would deploy each of the templates in the armTemplates list parallelly with multiple jobs. 120 | 121 | ```yml 122 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 123 | 124 | parameters: 125 | # params to pass into stages.yaml template: 126 | 127 | - name: deployPool # Nested into pool param of deploy jobs 128 | type: object 129 | default: 130 | vmImage: 'ubuntu-18.04' 131 | - name: checkout 132 | type: string 133 | default: self 134 | - name: azureSubscription # Azure Subscription service connection name 135 | type: string 136 | default: '' 137 | - name: resourceGroupName # Azure Resource Group within the subscription 138 | type: string 139 | default: '' 140 | - name: armTemplates 141 | type: object 142 | default: 143 | - deployment: 'armTemplate1' # deployment name must be unique 144 | template: 'deployment1.json' 145 | parameters: 'parameters1.json' 146 | - deployment: 'armTemplate2' # deployment name must be unique 147 | template: 'deployment2.json' 148 | parameters: 'parameters2.json' 149 | - deployment: 'armTemplate3' # deployment name must be unique 150 | template: 'deployment3.json' 151 | parameters: 'parameters3.json' 152 | # Example when armTemplate3 dependsOn armTemplate1 and armTemplate2 succeeded 153 | dependsOn: 154 | - armTemplate1 155 | - armTemplate2 156 | - name: templatePath # Root path of ARM templates 157 | type: string 158 | default: '$(Build.Repository.LocalPath)' 159 | 160 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 161 | 162 | resources: 163 | repositories: 164 | - repository: templates # Resource identifier for template usage 165 | type: github 166 | name: fitchtech/AzurePipelines # This repository 167 | ref: refs/tags/v1 # The tagged release of the repository 168 | endpoint: GitHub # Azure Service Connection Name 169 | 170 | trigger: 171 | branches: 172 | include: 173 | - master # CI Trigger on commit to master 174 | tags: 175 | include: 176 | - v*.*.*-* # CI Trigger when tag matches format 177 | 178 | extends: 179 | # template: file path at repo resource id to extend from 180 | template: stages.yaml@templates 181 | # parameters: within stages.yaml@templates 182 | parameters: 183 | # code: jobList inserted into code stage in stages 184 | # build: jobList inserted into build stage in stages 185 | # deploy: deploymentList inserted into deploy stage in stages param 186 | deploy: 187 | # - for each deployment item in armTemplates parameter insert arm deployment job 188 | - ${{ each deployment in parameters.armTemplates }}: 189 | - ${{ if and(deployment.deployment, deployment.template, parameters.azureSubscription, parameters.resourceGroupName) }}: 190 | - deployment: ${{ deployment.deployment }} # deployment name unique to stage 191 | displayName: 'Deploy ARM Template ${{ arm.template }}' 192 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 193 | ${{ if deployment.condition }}: 194 | condition: ${{ deployment.condition }} 195 | ${{ if not(deployment.condition) }}: 196 | condition: succeeded() 197 | # variables: 198 | # key: 'value' # pairs of variables scoped to this job 199 | ${{ if deployment.dependsOn }}: 200 | dependsOn: 201 | - ${{ each dependency in deployment.dependsOn }}: 202 | - ${{ dependency }} 203 | ${{ if not(deployment.dependsOn) }}: 204 | dependsOn: [] 205 | strategy: 206 | runOnce: 207 | deploy: 208 | steps: 209 | - template: steps/deploy/armTemplate.yaml 210 | parameters: 211 | # preSteps: 212 | # - task: add preSteps into job 213 | azureSubscription: ${{ parameters.azureSubscription }} # Service connection to subscription for the resource group 214 | resourceGroupName: ${{ parameters.resourceGroupName }} # RM Group name within subscription 215 | templatePath: '${{ parameters.templatePath }}' # root path where ARM templates are located 216 | templateFile: ${{ deployment.template }} # ARM template within deploymentDir 217 | ${{ if deployment.parameters }}: 218 | parametersFile: ${{ deployment.parameters }} # Parameters file within deploymentDir 219 | ${{ if deployment.override }}: 220 | overrideParameters: '${{ deployment.override }}' # Optionally add args to override values in parameters file 221 | # postSteps: 222 | # - task: add postSteps into job 223 | 224 | # - deployment: insert additional deployment jobs into the deploy stage 225 | 226 | # promote: deploymentList inserted into promote stage in stages param 227 | # test: jobList inserted into test stage in stages param 228 | # reject: deploymentList inserted into reject stage in stages param 229 | 230 | ``` 231 | -------------------------------------------------------------------------------- /docs/steps/deploy/helmChart.md: -------------------------------------------------------------------------------- 1 | # Helm Chart Steps Template 2 | 3 | - [Helm Chart Steps Template](#helm-chart-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | 7 | ## Steps Template Usage 8 | 9 | - The helmChart steps template uses the 'helm install/upgrade' command to deploy helm charts directly to a Kubernetes cluster 10 | - Alternatively, the [helmManifest](helmManifest.md) steps template uses the 'helm template' command to render Helm charts into manifests which are deployed to Kubernetes 11 | 12 | ## Insert Steps Template into Stages Template 13 | 14 | The following example shows how to insert the helmChart steps template into the [stages](../../stages.md) template with the minimum required params. 15 | 16 | ```yml 17 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 18 | 19 | parameters: 20 | # params to pass into stages.yaml template: 21 | 22 | - name: deployPool # Nested into pool param of deploy jobs 23 | type: object 24 | default: 25 | vmImage: 'ubuntu-18.04' 26 | - name: kubeServiceConnection # Kubernetes Service Connection Name 27 | type: string 28 | default: '' 29 | - name: kubeNamespace # Kubernetes Namespace for Helm Charts 30 | type: string 31 | default: default 32 | - name: helmChartPath # helmChartPath within Pipeline.Workspace where charts are located 33 | type: string 34 | default: 'helm' 35 | - name: helmValueFile # values file within helmChartPath 36 | type: string 37 | default: 'values.yaml' 38 | 39 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 40 | 41 | resources: 42 | repositories: 43 | - repository: templates # Resource identifier for template usage 44 | type: github 45 | name: fitchtech/AzurePipelines # This repository 46 | ref: refs/tags/v1 # The tagged release of the repository 47 | endpoint: GitHub # Azure Service Connection Name 48 | 49 | trigger: 50 | branches: 51 | include: 52 | - master # CI Trigger on commit to master 53 | tags: 54 | include: 55 | - v*.*.*-* # CI Trigger when tag matches format 56 | 57 | extends: 58 | # template: file path at repo resource id to extend from 59 | template: stages.yaml@templates 60 | # parameters: within stages.yaml@templates 61 | parameters: 62 | # code: jobList inserted into code stage in stages 63 | # build: jobList inserted into build stage in stages 64 | # deploy: deploymentList inserted into deploy stage in stages param 65 | deploy: 66 | - deployment: helmDeploy # job name unique to stage 67 | displayName: 'Deploy Helm Charts' 68 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 69 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 70 | # variables: 71 | # key: 'value' # pairs of variables scoped to this job 72 | dependsOn: [] 73 | strategy: 74 | runOnce: 75 | deploy: 76 | steps: 77 | - template: steps/deploy/helmChart.yaml 78 | parameters: 79 | # preSteps: 80 | # - task: add preSteps into job 81 | namespace: ${{ parameters.kubeNamespace }} # pass in namespace param 82 | kubernetesServiceConnection: ${{ parameters.kubeServiceConnection }} # pass param for kube manifest deployment service connection 83 | helmChartPath: '$(Pipeline.Workspace)/${{ parameters.helmChartPath }}' # helmChartPath within Pipeline.Workspace where charts are located 84 | helmValueFile: '$(Pipeline.Workspace)/${{ parameters.helmChartPath }}/${{ parameters.helmValueFile }}' # values file within helmChartPath 85 | # postSteps: 86 | # - task: add postSteps into job 87 | 88 | # - deployment: insert additional deployment jobs into the deploy stage 89 | 90 | # promote: deploymentList inserted into promote stage in stages param 91 | # test: jobList inserted into test stage in stages param 92 | # reject: deploymentList inserted into reject stage in stages param 93 | 94 | ``` 95 | -------------------------------------------------------------------------------- /docs/steps/deploy/helmManifest.md: -------------------------------------------------------------------------------- 1 | # Helm Manifest Steps Template 2 | 3 | - [Helm Manifest Steps Template](#helm-manifest-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | 7 | ## Steps Template Usage 8 | 9 | - The 'helm template' command is used to render Helm charts into Kubernetes Manifests which are then deployed via the service connection 10 | - This steps template nests [helmTemplate](../build/helmTemplate.md) and [kubeManifest](kubeManifest.md) steps templates 11 | 12 | ## Insert Steps Template into Stages Template 13 | 14 | The following example shows how to insert the helmManifest steps template into the [stages](../../stages.md) template with the minimum required params. 15 | 16 | ```yml 17 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 18 | 19 | parameters: 20 | # params to pass into stages.yaml template: 21 | 22 | - name: deployPool # Nested into pool param of deploy jobs 23 | type: object 24 | default: 25 | vmImage: 'ubuntu-18.04' 26 | - name: kubeServiceConnection # Kubernetes Service Connection Name 27 | type: string 28 | default: '' 29 | - name: kubeNamespace 30 | type: string 31 | default: default 32 | - name: helmChartPath 33 | type: string 34 | default: 'helm' 35 | - name: helmValueFile 36 | type: string 37 | default: 'values.yaml' 38 | 39 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 40 | 41 | resources: 42 | repositories: 43 | - repository: templates # Resource identifier for template usage 44 | type: github 45 | name: fitchtech/AzurePipelines # This repository 46 | ref: refs/tags/v1 # The tagged release of the repository 47 | endpoint: GitHub # Azure Service Connection Name 48 | 49 | trigger: 50 | branches: 51 | include: 52 | - master # CI Trigger on commit to master 53 | tags: 54 | include: 55 | - v*.*.*-* # CI Trigger when tag matches format 56 | 57 | extends: 58 | # template: file path at repo resource id to extend from 59 | template: stages.yaml@templates 60 | # parameters: within stages.yaml@templates 61 | parameters: 62 | # code: jobList inserted into code stage in stages 63 | # build: jobList inserted into build stage in stages 64 | # deploy: deploymentList inserted into deploy stage in stages param 65 | deploy: 66 | - deployment: helmDeploy # job name unique to stage 67 | displayName: 'Render Helm Charts and Deploy Manifests' 68 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 69 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 70 | # variables: 71 | # key: 'value' # pairs of variables scoped to this job 72 | dependsOn: [] 73 | strategy: 74 | runOnce: 75 | deploy: 76 | steps: 77 | - template: steps/deploy/helmManifest.yaml 78 | parameters: 79 | # preSteps: 80 | # - task: add preSteps into job 81 | namespace: ${{ parameters.kubeNamespace }} # pass in namespace param 82 | kubernetesServiceConnection: ${{ parameters.kubeServiceConnection }} # pass param for kube manifest deployment service connection 83 | helmChartPath: '$(Pipeline.Workspace)/${{ parameters.helmChartPath }}' # helmChartPath within Pipeline.Workspace where charts are located 84 | helmValueFile: '$(Pipeline.Workspace)/${{ parameters.helmChartPath }}/${{ parameters.helmValueFile }}' # values file within helmChartPath 85 | # postSteps: 86 | # - task: add postSteps into job 87 | 88 | # - deployment: insert additional deployment jobs into the deploy stage 89 | 90 | # promote: deploymentList inserted into promote stage in stages param 91 | # test: jobList inserted into test stage in stages param 92 | # reject: deploymentList inserted into reject stage in stages param 93 | 94 | ``` 95 | -------------------------------------------------------------------------------- /docs/steps/deploy/kubeManifest.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Manifest Steps Template 2 | 3 | - [Kubernetes Manifest Steps Template](#kubernetes-manifest-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 6 | 7 | ## Steps Template Usage 8 | 9 | - Deploy Kubernetes Manifests to the Kubernetes Service Connection or ADO Environment Resource 10 | - Deploy standard or canary pods for deployment manifests 11 | - Create/update image pull secret using docker and Kubernetes service connection 12 | - Bake Kustomize, Docker Compose, or Helm2 charts that are then deployed 13 | - Scale an existing replica set 14 | - Delete a Kubernetes object 15 | - Create Kubernetes secrets from Azure KeyVault Secrets 16 | 17 | ## Insert Steps Template into Stages Template 18 | 19 | The following example shows how to insert the kubeManifest steps template into the [stages](../../stages.md) template with the minimum required params. 20 | 21 | ```yml 22 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 23 | 24 | parameters: 25 | # params to pass into stages.yaml template: 26 | 27 | - name: deployPool # Nested into pool param of deploy jobs 28 | type: object 29 | default: 30 | vmImage: 'ubuntu-18.04' 31 | - name: dockerRegistryEndpoint # Container registry and Kubernetes service connection params used to create image pull secret in Kubernetes for the registry 32 | type: string 33 | default: '' # ADO Service Connection name 34 | - name: kubernetesServiceConnection # Kubernetes Service Connection Name 35 | type: string 36 | default: '' 37 | - name: namespace 38 | type: string 39 | default: default 40 | - name: manifests # Deployment manifest for canary deploy, promote, and reject jobs 41 | type: object 42 | default: '$(Pipeline.Workspace)/**deployment.yaml' 43 | - name: strategy 44 | type: string 45 | default: canary 46 | values: 47 | - canary 48 | - runOnce 49 | 50 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 51 | 52 | resources: 53 | repositories: 54 | - repository: templates # Resource identifier for template usage 55 | type: github 56 | name: fitchtech/AzurePipelines # This repository 57 | ref: refs/tags/v1 # The tagged release of the repository 58 | endpoint: GitHub # Azure Service Connection Name 59 | 60 | trigger: 61 | branches: 62 | include: 63 | - master # CI Trigger on commit to master 64 | tags: 65 | include: 66 | - v*.*.*-* # CI Trigger when tag matches format 67 | 68 | extends: 69 | # template: file path at repo resource id to extend from 70 | template: stages.yaml@templates 71 | # parameters: within stages.yaml@templates 72 | parameters: 73 | # code: jobList inserted into code stage in stages 74 | # build: jobList inserted into build stage in stages 75 | # deploy: deploymentList inserted into deploy stage in stages param 76 | deploy: 77 | - deployment: kubeDeploy # job name unique to stage 78 | displayName: 'Canary Deployment' 79 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 80 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 81 | # variables: 82 | # key: 'value' # pairs of variables scoped to this job 83 | dependsOn: [] 84 | strategy: 85 | ${{ parameters.strategy }}: 86 | deploy: 87 | steps: 88 | - template: steps/deploy/kubeManifest.yaml 89 | parameters: 90 | # preSteps: 91 | # - task: add preSteps into job 92 | namespace: ${{ parameters.namespace }} # pass in namespace param 93 | imagePullSecret: 'registry-cred' 94 | dockerRegistryEndpoint: ${{ parameters.dockerRegistryEndpoint }} 95 | kubernetesServiceConnection: ${{ parameters.kubernetesServiceConnection }} # pass param for kube manifest deployment service connection 96 | action: deploy 97 | strategy: ${{ parameters.strategy }} 98 | manifests: ${{ parameters.manifests }} 99 | # postSteps: 100 | # - task: add postSteps into job 101 | 102 | # promote: deploymentList inserted into promote stage in stages param 103 | promote: 104 | - ${{ if eq(parameters.strategy, 'canary') }}: 105 | - deployment: kubePromote # job name unique to stage 106 | displayName: 'Promote Canary Deployment' 107 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 108 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) 109 | # variables: 110 | # key: 'value' # pairs of variables scoped to this job 111 | dependsOn: [] 112 | strategy: 113 | runOnce: 114 | deploy: 115 | steps: 116 | - template: steps/deploy/kubeManifest.yaml 117 | parameters: 118 | # preSteps: 119 | # - task: add preSteps into job 120 | namespace: ${{ parameters.namespace }} # pass in namespace param 121 | kubernetesServiceConnection: ${{ parameters.kubernetesServiceConnection }} # pass param for kube manifest deployment service connection 122 | action: promote 123 | strategy: canary 124 | manifests: ${{ parameters.manifests }} 125 | # postSteps: 126 | # - task: add postSteps into job 127 | 128 | # reject: deploymentList inserted into reject stage in stages param 129 | reject: 130 | - ${{ if eq(parameters.strategy, 'canary') }}: 131 | - deployment: kubeReject # job name unique to stage 132 | displayName: 'Reject Canary Deployment' 133 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 134 | condition: and(failed(), ne(variables['Build.Reason'], 'PullRequest')) 135 | # variables: 136 | # key: 'value' # pairs of variables scoped to this job 137 | dependsOn: [] 138 | strategy: 139 | runOnce: 140 | deploy: 141 | steps: 142 | - template: steps/deploy/kubeManifest.yaml 143 | parameters: 144 | # preSteps: 145 | # - task: add preSteps into job 146 | namespace: ${{ parameters.namespace }} # pass in namespace param 147 | kubernetesServiceConnection: ${{ parameters.kubernetesServiceConnection }} # pass param for kube manifest deployment service connection 148 | action: reject 149 | strategy: canary 150 | manifests: ${{ parameters.manifests }} 151 | # postSteps: 152 | # - task: add postSteps into job 153 | 154 | # test: jobList inserted into test stage in stages param 155 | 156 | ``` 157 | -------------------------------------------------------------------------------- /docs/steps/deploy/terraformTemplate.md: -------------------------------------------------------------------------------- 1 | # Terraform Template Steps Template 2 | 3 | - [Terraform Template Steps Template](#terraform-template-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Steps Template Schema](#steps-template-schema) 6 | - [Deployment of Terraform Templates](#deployment-of-terraform-templates) 7 | 8 | ## Steps Template Usage 9 | 10 | - Inserts Terraform command tasks for each listed in commands parameter. e.g. - init, - plan, - validate, - apply, - destroy 11 | - Terraform commands run in the order listed in the commands parameter 12 | - Commands parameter is a list object where each item key is the command and value is commandOptions. e.g. commands: - apply: '-var="foo=bar"' 13 | - Set task options and command flags for each Terraform command 14 | - Optionally insert Terraform install task 15 | - Commands: 16 | - init 17 | - plan 18 | - validate 19 | - apply: '-var="$(variableKey)=$(variableValue)" 20 | - destroy 21 | 22 | ## Steps Template Schema 23 | 24 | ```yaml 25 | steps: 26 | # - template: for Terraform steps 27 | - template: steps/deploy/terraformTemplate.yaml 28 | # parameters: within terraformTemplate.yaml template 29 | parameters: 30 | # preSteps: Optional: inserts stepList after checkout and download 31 | preSteps: 32 | - script: echo add stepList of tasks into steps 33 | terraformVersion: '0.12.3' # Optional, the version of Terraform which should be installed on the agent if not already present. Omit terraformVersion parameter to skip task 34 | # provider: azurerm # azurerm (default) | aws | gcp 35 | serviceConnection: serviceConnectionName # Required service connection name for provider 36 | # commands: list of Terraform command tasks executed serially in order. -command: commandOptions 37 | commands: 38 | - init 39 | - plan: '-var "foo=bar"' 40 | - validate 41 | - apply: '-var "foo=bar"' 42 | - destroy 43 | condition: failed() 44 | workingDirectory: $(Build.Repository.LocalPath) # Directory containing the Terraform configuration files 45 | # AzureRM Provider Terraform Storage Backend 46 | resourceGroupName: resourceGroupName # Required for AzurRM provider, the name of the resource group which contains the storage account selected below. 47 | storageAccountName: storageAccountName # Required for AzurRM provider, the name of the storage account which contains the Azure Blob container selected below. 48 | containerName: containerName # Required for AzurRM provider, the name of the Azure Blob container in which to store the Terraform remote state file. 49 | backendKey: 'terraform.tfstate' # The path to the Terraform remote state file inside the container. Used for azurerm and aws provider 50 | # bucketName: bucketName # Required for AWS or GCP provider, the name of the Amazon Simple Storage Service(S3) bucket or GCP storage bucket for storing the Terraform remote state file. 51 | # publishPlan: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)_OutputPlan' # Default publish artifact name for $(jsonPlanFilePath) 52 | # publishVariables: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)_OutputVariables' # Default publish artifact for $(jsonOutputVariablesPath) 53 | # publishEnabled: false # Disable the publish task, default true. Publishes the testResultsFolder 54 | replaceTokens: true # Optional to enable replace tokens task for variable replacement 55 | replaceTokensTargets: '**.tf*' # Target file match pattern for replace tokens task 56 | # postSteps: Optional: inserts stepList before the publish and clean steps 57 | postSteps: 58 | - script: echo add stepList of tasks into steps 59 | 60 | ``` 61 | 62 | ## Deployment of Terraform Templates 63 | 64 | The following example shows how to insert the terraformTemplate steps template into the [stages](../../stages.md) template. This pattern would deploy each of the templates in the terraformDeployments list with multiple jobs in parallel or with dependencies. 65 | 66 | ```yaml 67 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 68 | 69 | parameters: 70 | # params to pass into stages.yaml template 71 | - name: terraformVersion # The version of Terraform which should be installed on the agent if not already present 72 | type: string 73 | default: '0.12.3' 74 | - name: terraformDeployments 75 | type: object 76 | default: 77 | - deployment: 'terraformTemplate1' # deployment name must be unique 78 | workingDirectory: '$(Build.Repository.LocalPath)/template1' 79 | - deployment: 'terraformTemplate2' # deployment name must be unique 80 | workingDirectory: '$(Build.Repository.LocalPath)/template2' 81 | - deployment: 'terraformTemplate3' # deployment name must be unique 82 | workingDirectory: '$(Build.Repository.LocalPath)/template3' 83 | # Example when terraformTemplate3 dependsOn terraformTemplate1 and terraformTemplate2 succeeded 84 | dependsOn: 85 | - terraformTemplate1 86 | - terraformTemplate2 87 | - name: terraformCommands # Default Terraform commands to execute in this order. Set value for command for commandOptions, - command: commandOptions | e.g. - apply: '-var "foo=bar"' 88 | type: object 89 | default: 90 | - init 91 | - plan 92 | - apply 93 | - name: azureSubscription # Default Azure Subscription service connection name for all jobs 94 | type: string 95 | default: '' 96 | - name: resourceGroupName # Default Azure Resource Group within the subscription for all jobs 97 | type: string 98 | default: '' 99 | - name: storageAccountName # Required for AzurRM provider, the name of the storage account which contains the Azure Blob container selected below. 100 | type: string 101 | default: '' 102 | - name: containerName # Required for AzurRM provider, the name of the Azure Blob container in which to store the Terraform remote state file. 103 | type: string 104 | default: '' 105 | - name: deployPool # Default pool param for all deploy jobs 106 | type: object 107 | default: 108 | vmImage: 'ubuntu-18.04' 109 | - name: checkout # Default checkout repository 110 | type: string 111 | default: self 112 | 113 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 114 | 115 | resources: 116 | repositories: 117 | - repository: templates # Resource identifier for template usage 118 | type: github 119 | name: fitchtech/AzurePipelines # This repository 120 | ref: refs/tags/v1 # The tagged release of the repository 121 | endpoint: GitHub # Azure Service Connection Name 122 | 123 | trigger: 124 | branches: 125 | include: 126 | - master # CI Trigger on commit to master 127 | tags: 128 | include: 129 | - v*.*.*-* # CI Trigger when tag matches format 130 | 131 | extends: 132 | # template: file path at repo resource id to extend from 133 | template: stages.yaml@templates 134 | # parameters: within stages.yaml@templates 135 | parameters: 136 | # code: jobList inserted into code stage in stages 137 | # build: jobList inserted into build stage in stages 138 | # deploy: deploymentList inserted into deploy stage in stages param 139 | deploy: 140 | # - for each deployment item in terraformDeployments parameter insert arm deployment job 141 | - ${{ each deployment in parameters.terraformDeployments }}: 142 | - ${{ if and(deployment.deployment, deployment.template, parameters.azureSubscription, parameters.resourceGroupName) }}: 143 | - deployment: ${{ deployment.deployment }} # deployment name unique to stage 144 | displayName: 'Deploy Terraform Template' 145 | pool: ${{ parameters.deployPool }} # param passed to pool of deployment jobs 146 | ${{ if deployment.condition }}: 147 | condition: ${{ deployment.condition }} 148 | ${{ if not(deployment.condition) }}: 149 | condition: succeeded() 150 | # variables: 151 | # key: 'value' # pairs of variables scoped to this job 152 | ${{ if deployment.dependsOn }}: 153 | dependsOn: ${{ deployment.dependsOn }} 154 | ${{ if not(deployment.dependsOn) }}: 155 | dependsOn: [] 156 | strategy: 157 | runOnce: 158 | deploy: 159 | steps: 160 | - template: steps/deploy/terraformTemplate.yaml 161 | parameters: 162 | # preSteps: 163 | # - task: add preSteps into job 164 | ${{ each param in deployment }}: 165 | ${{ if in(param.key, 'azureSubscription', 'resourceGroupName', 'storageAccountName', 'containerName', 'workingDirectory', 'commands') }}: 166 | ${{ param.key }}: ${{ param.value }} 167 | ${{ if not(deployment.commands) }}: 168 | commands: ${{ parameters.terraformCommands }} 169 | ${{ if and(not(deployment.azureSubscription), parameters.azureSubscription) }}: 170 | azureSubscription: ${{ parameters.azureSubscription }} # Service connection to subscription for the resource group 171 | ${{ if and(not(deployment.resourceGroupName), parameters.resourceGroupName) }}: 172 | resourceGroupName: ${{ parameters.resourceGroupName }} # RM Group name within subscription 173 | ${{ if and(not(deployment.storageAccountName), parameters.storageAccountName) }}: 174 | storageAccountName: '${{ parameters.storageAccountName }}' # root path where Terraform templates are located 175 | ${{ if and(not(deployment.containerName), parameters.containerName) }}: 176 | containerName: '${{ parameters.containerName }}' # root path where Terraform templates are located 177 | ${{ if and(not(deployment.workingDirectory), parameters.workingDirectory) }}: 178 | workingDirectory: '${{ parameters.workingDirectory }}' # root path where Terraform templates are located 179 | ${{ if parameters.terraformVersion }}: 180 | terraformVersion: ${{ parameters.terraformVersion }} 181 | # postSteps: 182 | # - task: add postSteps into job 183 | 184 | # - deployment: insert additional deployment jobs into the deploy stage 185 | 186 | # promote: deploymentList inserted into promote stage in stages param 187 | # test: jobList inserted into test stage in stages param 188 | # reject: deploymentList inserted into reject stage in stages param 189 | 190 | ``` 191 | -------------------------------------------------------------------------------- /docs/steps/test.md: -------------------------------------------------------------------------------- 1 | # Test Job Documentation 2 | 3 | | Documentation | Description | 4 | | ------------------------------------------------- | -------------------------------------- | 5 | | [Visual Studio Tests](./test/visualStudioTest.md) | Run VS Test suites in a dotNet project | 6 | -------------------------------------------------------------------------------- /docs/steps/test/visualStudioTest.md: -------------------------------------------------------------------------------- 1 | # Visual Studio Test Steps Template 2 | 3 | - [Visual Studio Test Steps Template](#visual-studio-test-steps-template) 4 | - [Steps Template Usage](#steps-template-usage) 5 | - [Steps Template Schema](#steps-template-schema) 6 | - [Insert Steps Template into Stages Template](#insert-steps-template-into-stages-template) 7 | 8 | ## Steps Template Usage 9 | 10 | - This template is used to run VSTest jobs for tests such as Build Verification or Functional Tests 11 | - To run the test the job needs to dotNet build the test project or download an artifact of the build. 12 | - This template has an option to replace tokens in target files with variables. This is useful when you need to use variables to replace values in files 13 | - You can define the test plan and suite for a vsTest. This requires you [create a test plan](https://docs.microsoft.com/en-us/azure/devops/test/create-a-test-plan?view=azure-devops) in Azure DevOps 14 | 15 | ## Steps Template Schema 16 | 17 | ```yml 18 | steps: 19 | # - template: for vsTest steps 20 | - template: steps/test/visualStudioTest.yaml 21 | # parameters: within visualStudioTest.yaml template 22 | parameters: 23 | # preSteps: Optional: inserts stepList after checkout and download 24 | preSteps: 25 | - script: echo add stepList of tasks into steps 26 | replaceTokens: true # Enable replace tokens task for variable replacement 27 | replaceTokensTargets: '**appsettings.*.json' # Target file match pattern for replace tokens task 28 | keyVaultName: keyVaultName # Get secrets from an Azure KeyVault. Useful with replace tokens task when you need to inject secrets into settings 29 | keyVaultSubscription: 'subscriptionServiceConnection' # Azure service connection to subscription of Azure KeyVault 30 | testPlan: 123456 # The ID number of the testPlan 31 | testSuite: 123456 # The ID number of the testSuite 32 | testConfiguration: 523 # The ID number of the testConfiguration 33 | testRunTitle: 'Test Run Title' 34 | testDiagnosticsEnabled: false # Default: true 35 | testCollectDumpOn: always # Default: onAbortOnly | always | never 36 | runInParallel: false # Default: true | run tests serially or in parallel 37 | rerunMaxAttempts: 2 38 | continueOnError: true 39 | distributionBatchType: basedOnExecutionTime # default: basedOnTestCases | basedOnExecutionTime | basedOnAssembly 40 | customBatchSizeValue: 10 # Optional when distributionBatchType is basedOnExecutionTime. Value greater than 0 enables batchingBasedOnAgentsOption: customBatchSize 41 | customRunTimePerBatchValue: 10 # Optional when distributionBatchType is BasedOnExecutionTime 42 | dotNetProjects: '*.sln' # Optional: File matching pattern to Visual Studio solution (*.sln) or dotNet project (*.csproj) to restore. 43 | dotNetVersion: '3.1.x' # Optional: if param has value, use dotNet version task inserted 44 | dotNetFeedRestore: '' # Optional: GUID of Azure artifact feed. Use when projects restore NuGet artifacts from a private feed 45 | dotNetArguments: '' # Optional: Additional arguments for projects if command is build or publish. Excluding '--no-restore' and '--output' as they are predefined 46 | publishEnabled: false # Disable the publish task, default true. Publishes the testResultsFolder 47 | publishArtifact: 'artifactName' # Default: $(Build.DefinitionName)_$(System.JobName) 48 | # postSteps: Optional: inserts stepList before publish and clean 49 | postSteps: 50 | - script: echo add stepList of tasks into steps 51 | 52 | ``` 53 | 54 | ## Insert Steps Template into Stages Template 55 | 56 | The following example shows how to insert the Visual Studio Test steps template into the [stages](../../stages.md) template. 57 | 58 | ```yml 59 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 60 | 61 | parameters: 62 | # params to pass into stages.yaml template: 63 | - name: testPool 64 | type: object 65 | default: 66 | vmImage: 'windows-latest' # Nested into pool param of test jobs 67 | - name: vsTests 68 | type: object 69 | default: 70 | - job: vsTest 71 | dependsOn: [] 72 | dotNetProjects: '*.csproj' 73 | testPlan: 123456 74 | testSuite: 123456 75 | testConfiguration: 523 76 | testRunTitle: 'Functional Test' 77 | rerunMaxAttempts: 2 78 | continueOnError: false 79 | 80 | - name: matrix 81 | type: object 82 | default: '' 83 | - name: parallel 84 | type: number 85 | default: 1 86 | 87 | # parameter defaults in the above section can be set on the manual run of a pipeline to override 88 | 89 | resources: 90 | repositories: 91 | - repository: templates # Resource identifier for template usage 92 | type: github 93 | name: fitchtech/AzurePipelines # This repository 94 | ref: refs/tags/v1 # The tagged release of the repository 95 | endpoint: GitHub # Azure Service Connection Name 96 | 97 | trigger: 98 | branches: 99 | include: 100 | - master # CI Trigger on commit to master 101 | tags: 102 | include: 103 | - v*.*.*-* # CI Trigger when tag matches format 104 | 105 | extends: 106 | # template: file path at repo resource id to extend from 107 | template: stages.yaml@templates 108 | # parameters: within stages.yaml@templates 109 | parameters: 110 | # code: jobList inserted into code stage in stages 111 | # build: jobList inserted into build stage in stages param 112 | # deploy: deploymentList inserted into deploy stage in stages param 113 | # promote: deploymentList inserted into promote stage in stages param 114 | # test: jobList inserted into test stage in stages param 115 | test: 116 | - ${{ each test in parameters.vsTests }}: 117 | # This expression would require you provide a dotNet project to build and the test plan and suite ID 118 | - ${{ if and(test.job, test.dotNetProjects, parameters.testPlan, parameters.testSuite) }}: 119 | # - job: name must be unique within stage 120 | - job: ${{ test.job }} 121 | # for each job param of test item in vsTests, insert param 122 | ${{ each parameter in test }}: 123 | ${{ if in(parameter.key, 'displayName', 'condition', 'continueOnError', 'pool', 'workspace', 'container', 'timeoutInMinutes', 'cancelTimeoutInMinutes', 'services') }}: 124 | ${{ parameter.key }}: ${{ parameter.value }} 125 | # If test job depends on other jobs in test stage insert dependencies 126 | ${{ if test.dependsOn }}: 127 | dependsOn: 128 | - ${{ each dependency in test.dependsOn }}: 129 | - ${{ dependency }} 130 | # If no test.dependsOn job does not depend on others 131 | ${{ if not(test.dependsOn) }}: 132 | dependsOn: [] 133 | # If variables defined add key value pairs 134 | ${{ if test.variables }}: 135 | variables: 136 | ${{ each variable in test.variables }}: 137 | ${{ variable.key }}: ${{ variable.value }} 138 | # If no test.displayName use default 139 | ${{ if not(test.displayName) }}: 140 | displayName: 'Visual Studio Test Job' 141 | # If no test.pool use parameters.testPool value 142 | ${{ if not(test.pool) }}: 143 | pool: ${{ parameters.testPool }} 144 | # If test.matrix or test.parallel strategy for Visual Studio Test jobs 145 | ${{ if or(test.matrix, gt(test.parallel, 1)) }}: 146 | strategy: 147 | ${{ if test.matrix }}: 148 | matrix: ${{ test.matrix }} 149 | ${{ if not(test.matrix) }}: 150 | parallel: ${{ test.parallel }} 151 | # If the test has no test.matrix or test.parallel values then use parameters.matrix and parameters.parallel as default 152 | ${{ if and(or(parameters.matrix, gt(parameters.parallel, 1)), not(test.matrix), le(test.parallel, 1)) }}: 153 | strategy: 154 | ${{ if parameters.matrix }}: 155 | matrix: ${{ parameters.matrix }} 156 | ${{ if not(parameters.matrix) }}: 157 | parallel: ${{ parameters.parallel }} 158 | steps: 159 | # - template: insert visualStudioTest template 160 | - template: steps/test/visualStudioTest.yaml 161 | # parameters within visualStudioTest.yaml template 162 | parameters: 163 | # preSteps: 164 | # - task: add preSteps into job 165 | # for each parameter in test that is not a job parameter, these are the parameters for the steps 166 | ${{ each parameter in test }}: 167 | ${{ if notIn(parameter.key, 'job', 'displayName', 'dependsOn', 'condition', 'strategy', 'continueOnError', 'pool', 'workspace', 'container', 'timeoutInMinutes', 'cancelTimeoutInMinutes', 'variables', 'steps', 'services') }}: 168 | ${{ parameter.key }}: ${{ parameter.value }} 169 | ${{ if not(test.testRunTitle) }}: 170 | testRunTitle: 'Visual Studio Test' 171 | # postSteps: 172 | # - task: add postSteps into job 173 | 174 | # - job: insert additional jobs into the test stage 175 | 176 | # reject: deploymentList inserted into reject stage in stages param 177 | 178 | ``` 179 | -------------------------------------------------------------------------------- /jobs/build.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: name # name of the job (A-Z, a-z, 0-9, and underscore) 3 | type: string 4 | default: build 5 | - name: displayName # friendly name to display in the UI 6 | type: string 7 | default: Build 8 | - name: dependsOn # string for dependsOn one job, list for dependsOn multiple jobs 9 | type: object 10 | default: [] 11 | - name: condition # default job condition 12 | type: string 13 | default: succeeded() 14 | - name: strategy # Optional, add strategy object to job for parallel or matrix strategy 15 | type: object 16 | default: '' 17 | - name: continueOnError # 'true' if future jobs should run even if this job fails; defaults to 'false' 18 | type: boolean 19 | default: false 20 | - name: pool # Optional, set pool object for a job to override pool set in the pipeline 21 | type: object 22 | default: '' 23 | - name: container # Optional container to run this job inside of 24 | type: object 25 | default: '' 26 | - name: timeoutInMinutes # how long to run the job before automatically cancelling 27 | type: number 28 | default: 0 29 | - name: cancelTimeoutInMinutes # how much time to give 'run always even if cancelled tasks' before killing them 30 | type: number 31 | default: 0 32 | - name: variables # map or list format of variables added to the job 33 | type: object 34 | default: '' 35 | - name: clean # if true, execute git clean for checkout step; clean workspace folders; and post build cleanup task 36 | type: boolean 37 | default: true 38 | - name: checkout # [ self | none | repository name ] # self represents the repo where the initial Pipelines YAML file was found 39 | type: string 40 | default: self 41 | - name: checkoutSubModules # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules; defaults to not checking out submodules 42 | type: boolean 43 | default: string 44 | values: 45 | - true 46 | - recursive 47 | - name: download # [ current | pipeline resource identifier | none ] # disable automatic download if "none" 48 | type: string 49 | default: current 50 | - name: artifact # artifact name, optional; for downloads all the available artifacts if not specified. For publish it's the artifact name 51 | type: string 52 | default: '' 53 | - name: preSteps # Optional list of tasks [ script | bash | pwsh | powershell | checkout | task | templateReference ] 54 | type: stepList 55 | default: [] 56 | - name: buildSteps # list of tasks [ script | bash | pwsh | powershell | checkout | task | templateReference ] 57 | type: stepList 58 | default: 59 | - template: buildSteps.yaml 60 | - name: postSteps # Optional list of tasks [ script | bash | pwsh | powershell | checkout | task | templateReference ] 61 | type: stepList 62 | default: [] 63 | - name: publish # path to a file or folder. Optional to enable task 64 | type: string 65 | default: '' 66 | 67 | jobs: 68 | - job: ${{ parameters.name }} 69 | displayName: ${{ parameters.displayName }} 70 | dependsOn: ${{ parameters.dependsOn }} 71 | condition: ${{ parameters.condition }} 72 | ${{ if parameters.strategy }}: 73 | strategy: ${{ parameters.strategy }} 74 | continueOnError: ${{ parameters.continueOnError }} 75 | ${{ if parameters.pool }}: 76 | pool: ${{ parameters.pool }} 77 | ${{ if parameters.clean }}: 78 | workspace: 79 | clean: all 80 | ${{ if parameters.container }}: 81 | container: ${{ parameters.container }} 82 | ${{ if gt(length(parameters.timeoutInMinutes), 0) }}: 83 | timeoutInMinutes: ${{ parameters.timeoutInMinutes }} 84 | ${{ if gt(length(parameters.cancelTimeoutInMinutes), 0) }}: 85 | cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} 86 | ${{ if parameters.variables }}: 87 | variables: ${{ parameters.variables }} 88 | steps: 89 | - ${{ if or(eq(parameters.checkout, ''), eq(parameters.checkout, 'none')) }}: 90 | - checkout: none 91 | - ${{ if or(ne(parameters.checkout, ''), ne(parameters.checkout, 'none')) }}: 92 | - checkout: ${{ parameters.checkout }} 93 | clean: ${{ parameters.clean }} 94 | submodules: ${{ parameters.checkoutSubModules }} 95 | - ${{ or(ne(parameters.download, 'none'), ne(parameters.download, '')) }}: 96 | - download: ${{ parameters.download }} 97 | ${{ if parameters.artifact }}: 98 | artifact: ${{ parameters.artifact }} 99 | - ${{ if gt(length(parameters.preSteps), 0) }}: 100 | - ${{ parameters.preSteps }} 101 | - ${{ parameters.buildSteps }} 102 | - ${{ if gt(length(parameters.postSteps), 0) }}: 103 | - ${{ parameters.postSteps }} 104 | - ${{ parameters.publish }}: 105 | - publish: ${{ parameters.publish }} 106 | ${{ if parameters.artifact }}: 107 | artifact: ${{ parameters.artifact }} 108 | - ${{ if parameters.clean }}: 109 | - task: PostBuildCleanup@3 110 | displayName: Clean Agent Directories 111 | env: 112 | Build.Clean: all -------------------------------------------------------------------------------- /jobs/deployment.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: deployment # name of the job (A-Z, a-z, 0-9, and underscore) 3 | type: string 4 | default: build 5 | - name: displayName # friendly name to display in the UI 6 | type: string 7 | default: Build 8 | - name: dependsOn # string for dependsOn one job, list for dependsOn multiple jobs 9 | type: object 10 | default: [] 11 | - name: condition # default job condition 12 | type: string 13 | default: succeeded() 14 | - name: continueOnError # 'true' if future jobs should run even if this job fails; defaults to 'false' 15 | type: boolean 16 | default: false 17 | - name: pool # Optional, set pool object for a job to override pool set in the pipeline 18 | type: object 19 | default: '' 20 | - name: container # Optional container to run this job inside of 21 | type: object 22 | default: '' 23 | - name: timeoutInMinutes # how long to run the job before automatically cancelling 24 | type: number 25 | default: 0 26 | - name: cancelTimeoutInMinutes # how much time to give 'run always even if cancelled tasks' before killing them 27 | type: number 28 | default: 0 29 | - name: variables # map or list format of variables added to the job 30 | type: object 31 | default: '' 32 | - name: clean # if true, execute git clean for checkout step; clean workspace folders; and post build cleanup task 33 | type: boolean 34 | default: true 35 | - name: checkout # [ self | none | repository name ] # self represents the repo where the initial Pipelines YAML file was found 36 | type: string 37 | default: self 38 | - name: checkoutSubModules # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules; defaults to not checking out submodules 39 | type: boolean 40 | default: string 41 | values: 42 | - true 43 | - recursive 44 | - name: download # [ current | pipeline resource identifier | none ] # disable automatic download if "none" 45 | type: string 46 | default: current 47 | - name: artifact # artifact name, optional; for downloads all the available artifacts if not specified. For publish it's the artifact name 48 | type: string 49 | default: '' 50 | - name: preSteps # Optional list of tasks [ script | bash | pwsh | powershell | checkout | task | templateReference ] 51 | type: stepList 52 | default: [] 53 | - name: postSteps # Optional list of tasks [ script | bash | pwsh | powershell | checkout | task | templateReference ] 54 | type: stepList 55 | default: [] 56 | - name: publish # path to a file or folder. Optional to enable task 57 | type: string 58 | default: '' 59 | 60 | # Deploy: lifecycle hooks 61 | - name: strategy # Optional, add strategy object to job for parallel or matrix strategy 62 | type: string 63 | default: runOnce 64 | values: 65 | - runOnce 66 | - canary 67 | - rolling 68 | - name: preDeploy # Deployment job preDeploy lifecycle hook 69 | type: stepList 70 | default: [] 71 | - name: routeTraffic # Deployment job routeTraffic lifecycle hook 72 | type: stepList 73 | default: [] 74 | - name: postRouteTraffic # Deployment job postRouteTraffic lifecycle hook 75 | type: stepList 76 | default: [] 77 | - name: onFailure # Deployment job on: failure: lifecycle hook 78 | type: stepList 79 | default: [] 80 | - name: onSuccess # Deployment job on: success: lifecycle hook 81 | type: stepList 82 | default: [] 83 | 84 | 85 | jobs: 86 | - deployment: ${{ parameters.deployment }} # job name unique to stage 87 | displayName: ${{ parameters.displayName }} 88 | ${{ if parameters.pool }}: 89 | pool: ${{ parameters.pool }} # Override parameters.deployPool with parameters.pool 90 | ${{ if parameters.condition }}: 91 | condition: ${{ parameters.condition }} 92 | ${{ if parameters.variables }}: 93 | variables: 94 | ${{ each variable in parameters.variables }}: 95 | ${{ variable.key }}: ${{ variable.value }} # pairs of variables scoped to this job 96 | ${{ if parameters.dependsOn }}: 97 | dependsOn: 98 | - ${{ each dependency in parameters.dependsOn }}: 99 | - ${{ dependency }} 100 | ${{ if not(parameters.dependsOn) }}: 101 | dependsOn: [] 102 | ${{ if parameters.environment }}: 103 | environment: ${{ parameters.environment }} 104 | strategy: 105 | ${{ parameters.strategy }}: 106 | ${{ if and(eq(parameters.strategy, 'canary'), parameters.increments) }}: 107 | increments: ${{ parameters.increments }} 108 | # Insert preDeploy lifecycle hook stepList 109 | ${{ if gt(length(parameters.preDeploy), 0) }}: 110 | preDeploy: 111 | ${{ if parameters.pool }}: 112 | pool: ${{ parameters.pool }} 113 | steps: 114 | - ${{ parameters.preDeploy }} 115 | deploy: 116 | steps: 117 | - template: ${{ parameters.stepsTemplate }} 118 | parameters: 119 | ${{ parameters.stepsParameters }} 120 | # Insert routeTraffic lifecycle hook stepList 121 | ${{ if gt(length(parameters.routeTraffic), 0) }}: 122 | routeTraffic: 123 | ${{ if parameters.pool }}: 124 | pool: ${{ parameters.pool }} 125 | steps: 126 | - ${{ parameters.routeTraffic }} 127 | # Insert postRouteTraffic lifecycle hook stepList 128 | ${{ if gt(length(parameters.postRouteTraffic), 0) }}: 129 | postRouteTraffic: 130 | ${{ if parameters.pool }}: 131 | pool: ${{ parameters.pool }} 132 | steps: 133 | - ${{ parameters.postRouteTraffic }} 134 | # Insert onFailure and onSuccess stepList 135 | ${{ if or(gt(length(parameters.onFailure), 0), gt(length(parameters.onSuccess), 0)) }}: 136 | on: 137 | ${{ if gt(length(parameters.onFailure), 0) }}: 138 | failure: 139 | ${{ if parameters.pool }}: 140 | pool: ${{ parameters.pool }} 141 | steps: 142 | - ${{ parameters.onFailure }} 143 | ${{ if gt(length(parameters.onSuccess), 0) }}: 144 | success: 145 | ${{ if parameters.pool }}: 146 | pool: ${{ parameters.pool }} 147 | steps: 148 | - ${{ parameters.onSuccess }} 149 | -------------------------------------------------------------------------------- /pipelines/jobTypes-dockerBuild.yaml: -------------------------------------------------------------------------------- 1 | # This pipeline is to test the syntax of the stages.yaml and presets/jobTypes.yaml templates 2 | name: $(Build.DefinitionName)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 3 | 4 | parameters: 5 | - name: dockerFile # Path to Dockerfile 6 | type: string 7 | default: 'BlazorServerApp/Dockerfile' 8 | - name: dockerTags # Default tags to set in addition to pipeline metadata tags 9 | type: object 10 | default: | 11 | $(dockerTag) 12 | $(buildVersion) 13 | - name: containerRegistry # Docker registry service connection name 14 | type: string 15 | default: DockerHub 16 | - name: containerRepository # docker.io/accountName/repositoryName 17 | type: string 18 | default: fitchtech/blazor 19 | - name: timeoutInMinutes # in each job, how long to run the job before automatically cancelling 20 | type: number 21 | default: 5 22 | - name: cancelTimeoutInMinutes # in each job, how much time to give 'run always even if cancelled tasks' before killing them 23 | type: number 24 | default: 1 25 | - name: checkout 26 | type: string 27 | default: blazor 28 | 29 | resources: 30 | repositories: 31 | - repository: blazor 32 | type: github 33 | name: fitchtech/BlazorServerApp 34 | ref: refs/heads/master 35 | endpoint: GitHub 36 | trigger: none 37 | 38 | trigger: 39 | branches: 40 | include: 41 | - master 42 | tags: 43 | include: 44 | - v1* 45 | 46 | variables: 47 | dockerTag: $[lower(variables['Build.BuildNumber'])] 48 | buildVersion: $[counter(variables['Build.SourceVersion'], 1)] 49 | 50 | extends: 51 | template: ../presets/jobTypes.yaml 52 | parameters: 53 | timeoutInMinutes: ${{ parameters.timeoutInMinutes }} 54 | cancelTimeoutInMinutes: ${{ parameters.cancelTimeoutInMinutes }} 55 | buildCheckout: ${{ parameters.checkout }} 56 | dockerFile: ${{ parameters.dockerFile }} 57 | dockerTags: ${{ parameters.dockerTags }} 58 | containerRegistry: ${{ parameters.containerRegistry }} 59 | containerRepository: ${{ parameters.containerRepository }} 60 | 61 | # dockerBuilds: 62 | # - job: containerImage 63 | # checkout: blazor 64 | # dockerFile: BlazorServerApp/Dockerfile 65 | # dockerTags: $(dockerTag) 66 | # containerRepository: fitchtech/blazor 67 | -------------------------------------------------------------------------------- /pipelines/stepLists-testScripts.yaml: -------------------------------------------------------------------------------- 1 | # This pipeline is to test the syntax of the stages.yaml and stepLists.yaml templates 2 | name: $(Build.Repository.Name)_$(Build.SourceVersion)_$(Build.SourceBranchName) # name is the format for $(Build.BuildNumber) 3 | 4 | trigger: 5 | branches: 6 | include: 7 | - master 8 | tags: 9 | include: 10 | - v1* 11 | 12 | extends: 13 | template: ../presets/stepLists.yaml 14 | parameters: 15 | timeoutInMinutes: 1 16 | cancelTimeoutInMinutes: 1 17 | codeSteps: 18 | - script: echo insert steps into stepList 19 | buildSteps: 20 | - script: echo insert steps into stepList 21 | deploySteps: 22 | - script: echo insert steps into stepList 23 | promoteSteps: 24 | - script: echo insert steps into stepList 25 | rejectSteps: 26 | - script: echo insert steps into stepList -------------------------------------------------------------------------------- /steps/build/containerImage.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | - name: downloadPath 22 | type: string 23 | default: '' 24 | # postSteps 25 | - name: postSteps 26 | type: stepList 27 | default: [] 28 | - name: publishArtifact 29 | type: string 30 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)' 31 | 32 | # dotNet Publish project to copy output into Docker image 33 | - name: dotNetType 34 | type: string 35 | default: runtime 36 | values: 37 | - sdk 38 | - runtime 39 | - name: dotNetCommand 40 | type: string 41 | default: publish 42 | values: 43 | - publish 44 | - build 45 | - name: dotNetVersion # Optional param to enable use dotNet task 46 | type: string 47 | default: '' 48 | - name: dotNetProjects # Required param to restore and publish a dotNet project 49 | type: string 50 | default: '' 51 | - name: dotNetArguments 52 | type: string 53 | default: '' 54 | - name: dotNetFeedRestore 55 | type: string 56 | default: '' 57 | - name: dotNetPublishWebProjects 58 | type: boolean 59 | default: false 60 | 61 | # Docker Instal Task (Optional) 62 | - name: dockerInstall # Optional to enable docker install on agent 63 | type: boolean 64 | default: false 65 | - name: dockerVersion # Optional to set specific docker version to install 66 | type: string 67 | default: '' 68 | - name: dockerReleaseType # Default docker release channel to install 69 | type: string 70 | default: stable 71 | values: 72 | - stable 73 | - edge 74 | - test 75 | - nightly 76 | # Docker Build and Push 77 | - name: dockerFile # Path to Dockerfile 78 | type: string 79 | default: '**.dockerfile' 80 | - name: dockerContext 81 | type: string 82 | default: '$(Build.Repository.LocalPath)' 83 | - name: dockerArgs # Optional param to pass build arguments to Docker 84 | type: string 85 | default: '' 86 | - name: dockerTags # Default tags to set in addition to pipeline metadata tags 87 | type: object 88 | default: $(Build.BuildNumber) 89 | - name: dockerPush # Enable push image to containerRegistry/containerRepository 90 | type: boolean 91 | default: true 92 | - name: dockerSave # Save the docker image built as an archive file to publish 93 | type: boolean 94 | default: false 95 | - name: containerRegistry # Service connection name. Container registry for Docker build and push 96 | type: string 97 | default: '' 98 | - name: containerRegistryUrl # Option URL of registry. Required if dockerSave: true 99 | type: string 100 | default: '' 101 | - name: containerRepository # Container repo path in registry for Docker push 102 | type: string 103 | default: '' 104 | - name: containerRegistries # List of container registries to login to. Useful when building images FROM multiple private registries. 105 | type: object 106 | default: '' 107 | # containerRegistries: 108 | # - registry1 109 | # - registry2 110 | 111 | # Twistlock Scan of Docker Image on ADO agent 112 | - name: twistlockService # Azure Service Connection name for Twistlock 113 | type: string 114 | default: '' 115 | - name: twistlockArtifact # Optional to set image to scan. Default scans image in build task 116 | type: string 117 | default: '$(Build.BuildNumber)' 118 | - name: twistlockContinue # continueOnError param for twistlock task 119 | type: boolean 120 | default: false 121 | - name: twistlockEnabled # true inserts twistlock task 122 | type: boolean 123 | default: false 124 | 125 | # Task to Archive and Pipeline Publish Artifact of dotNet project 126 | - name: deleteRoot 127 | type: string 128 | default: $(Pipeline.Workspace) 129 | - name: deleteContents # Default files to delete from archive artifact 130 | type: object 131 | default: '' 132 | - name: archiveArtifacts 133 | type: boolean 134 | default: false 135 | - name: archiveRoot # Default path to dotNet publish output 136 | type: string 137 | default: '$(Pipeline.Workspace)' 138 | - name: archiveFile 139 | type: string 140 | default: '$(Build.BuildNumber)' 141 | - name: archiveType 142 | type: string 143 | default: 'tar.gz' 144 | values: 145 | - 'tar.gz' 146 | - 'zip' 147 | 148 | steps: 149 | - template: ../preSteps.yaml 150 | parameters: 151 | clean: ${{ parameters.clean }} 152 | checkout: ${{ parameters.checkout }} 153 | submodules: ${{ parameters.submodules }} 154 | ${{ if and(not(parameters.downloadPath), parameters.downloadArtifact) }}: 155 | download: ${{ parameters.download }} 156 | artifact: ${{ parameters.downloadArtifact }} 157 | preSteps: ${{ parameters.preSteps }} 158 | - ${{ if and(parameters.downloadPath, parameters.downloadArtifact) }}: 159 | - task: DownloadPipelineArtifact@2 160 | displayName: Download Pipeline Artifact ${{ parameters.downloadArtifact }} 161 | inputs: 162 | artifact: ${{ parameters.downloadArtifact }} 163 | path: ${{ parameters.downloadPath }} 164 | - ${{ if parameters.dotNetProjects }}: 165 | - template: dotNetCore.yaml 166 | parameters: 167 | clean: false 168 | checkout: false 169 | download: false 170 | command: ${{ parameters.dotNetCommand }} 171 | packageType: ${{ parameters.dotNetType }} 172 | version: ${{ parameters.dotNetVersion }} 173 | projects: ${{ parameters.dotNetProjects }} 174 | feedRestore: ${{ parameters.dotNetFeedRestore }} 175 | arguments: ${{ parameters.dotNetArguments}} 176 | publishWebProjects: ${{ parameters.dotNetPublishWebProjects }} 177 | - ${{ if parameters.dockerInstall }}: 178 | - task: DockerInstaller@0 179 | displayName: 'Install Docker' 180 | target: host 181 | inputs: 182 | releaseType: ${{ parameters.dockerReleaseType }} 183 | ${{ if parameters.dockerVersion }}: 184 | dockerVersion: '${{ parameters.dockerVersion }}' 185 | - ${{ if parameters.containerRegistries }}: 186 | - ${{ each registry in parameters.containerRegistries }}: 187 | - task: Docker@2 188 | displayName: 'Login to ${{ registry }}' 189 | inputs: 190 | command: login 191 | containerRegistry: '${{ registry }}' 192 | - ${{ if and(parameters.containerRegistry, parameters.containerRepository) }}: 193 | - task: Docker@2 194 | displayName: 'Login to ${{ parameters.containerRegistry }}' 195 | inputs: 196 | command: login 197 | containerRegistry: '${{ parameters.containerRegistry }}' 198 | - task: Docker@2 199 | displayName: 'Build Docker Image' 200 | target: host 201 | inputs: 202 | containerRegistry: '${{ parameters.containerRegistry }}' 203 | repository: '${{ parameters.containerRepository }}' 204 | command: build 205 | Dockerfile: '${{ parameters.dockerFile }}' 206 | buildContext: '${{ parameters.dockerContext }}' 207 | ${{ if parameters.dockerArgs }}: 208 | arguments: '${{ parameters.dockerArgs }}' 209 | tags: ${{ parameters.dockerTags }} 210 | - ${{ if and(parameters.twistlockEnabled, parameters.twistlockArtifact, parameters.twistlockService) }}: 211 | - task: prisma-cloud-compute-scan@3 212 | displayName: 'Prisma Cloud Compute Scan' 213 | continueOnError: ${{ parameters.twistlockContinue }} 214 | inputs: 215 | scanType: 'images' 216 | twistlockService: '${{ parameters.twistlockService }}' 217 | artifact: '${{ parameters.twistlockArtifact }}' 218 | - ${{ if parameters.dockerPush }}: 219 | - task: Docker@2 220 | displayName: 'Push Docker Image to ${{ parameters.containerRegistry }}' 221 | target: host 222 | inputs: 223 | containerRegistry: '${{ parameters.containerRegistry }}' 224 | repository: '${{ parameters.containerRepository }}' 225 | command: push 226 | tags: ${{ parameters.dockerTags }} 227 | - ${{ if and(parameters.dockerSave, parameters.containerRegistryUrl) }}: 228 | - script: | 229 | docker save ${{ parameters.containerRegistryUrl }}/${{ parameters.containerRepository }}:latest -o ${{ parameters.archiveRoot }}/${{ parameters.archiveFile }}.${{ parameters.archiveType }} 230 | displayName: 'Docker Save ${{ parameters.containerRepository }}' 231 | - ${{ if and(parameters.archiveArtifacts, not(parameters.dockerSave)) }}: 232 | - ${{ if parameters.deleteContents }}: 233 | - task: DeleteFiles@1 234 | displayName: 'Delete Unwanted Files' 235 | inputs: 236 | SourceFolder: '${{ parameters.deleteRoot }}' 237 | Contents: ${{ parameters.deleteContents }} 238 | - task: ArchiveFiles@2 239 | displayName: 'Archive Published Artifacts' 240 | inputs: 241 | rootFolderOrFile: '${{ parameters.archiveRoot }}' 242 | includeRootFolder: false 243 | ${{ if eq(parameters.archiveType, 'tar.gz') }}: 244 | archiveType: tar 245 | tarCompression: gz 246 | ${{ if eq(parameters.archiveType, 'zip') }}: 247 | archiveType: zip 248 | archiveFile: '${{ parameters.archiveFile }}.${{ parameters.archiveType }}' 249 | replaceExistingArchive: true 250 | - template: ../postSteps.yaml 251 | parameters: 252 | postSteps: ${{ parameters.postSteps }} 253 | ${{ if or(parameters.archiveArtifacts, parameters.dockerSave) }}: 254 | publish: '${{ parameters.archiveRoot }}/${{ parameters.archiveFile }}.${{ parameters.archiveType }}' 255 | artifact: ${{ parameters.publishArtifact }} 256 | clean: ${{ parameters.clean }} 257 | -------------------------------------------------------------------------------- /steps/build/dotNetCore.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean # When nesting the dotNetCore.yaml into another steps template set clean: false 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout # When nesting the dotNetCore.yaml into another steps template set checkout: false 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download # When nesting the dotNetCore.yaml into another steps template set download: false 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | - name: downloadPath 22 | type: string 23 | default: '' 24 | # postSteps 25 | - name: postSteps 26 | type: stepList 27 | default: [] 28 | - name: publishArtifact 29 | type: string 30 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)' 31 | - name: publishEnabled 32 | type: boolean 33 | default: true 34 | # Use dotNet 35 | - name: version # Optional, inserts use dotNet task for version. e.g. version: '3.1.x' 36 | type: string 37 | default: '' 38 | - name: packageType # Use dotNet sdk or runtime 39 | type: string 40 | default: sdk 41 | values: 42 | - sdk 43 | - runtime 44 | # dotNet Core CLI 45 | - name: command 46 | type: string 47 | default: build 48 | values: 49 | - build 50 | - publish 51 | - restore 52 | - name: projects # Required param to restore and publish a dotNet project 53 | type: string 54 | default: '' 55 | - name: arguments 56 | type: string 57 | default: '' 58 | - name: feedRestore # dotNet restore feed 59 | type: string 60 | default: '' 61 | - name: publishWebProjects 62 | type: boolean 63 | default: false 64 | - name: nugetConfigPath # The NuGet.config in your repository that specifies the feeds from which to restore packages. 65 | type: string 66 | default: '' 67 | # dotNet Pack 68 | - name: searchPatternPack # Required to enable pack 69 | type: string 70 | default: '' 71 | - name: includeSymbols # dotNet pack includeSymbols 72 | type: boolean 73 | default: false 74 | - name: publishSymbols # Enable Publish Symbols task after dotNet pack 75 | type: boolean 76 | default: false 77 | - name: versioningScheme # byEnvVar is default, set value or EnvVar 78 | type: string 79 | default: byEnvVar 80 | values: 81 | - off 82 | - byPrereleaseNumber 83 | - byEnvVar 84 | - byBuildNumber 85 | - name: versionEnvVar # Name of environment variable to use for version number 86 | type: string 87 | default: NugetVersion 88 | - name: majorVersion # Required when versioningScheme is byPrereleaseNumber 89 | type: number 90 | default: 1 91 | - name: minorVersion # Required when versioningScheme is byPrereleaseNumber 92 | type: number 93 | default: 0 94 | - name: patchVersion # Required when versioningScheme is byPrereleaseNumber 95 | type: number 96 | default: 0 97 | - name: push # enables dotNet push after dotNet pack 98 | type: boolean 99 | default: true 100 | - name: feedPublish # dotNet push feed to publish of dotNet pack output NuGet package 101 | type: string 102 | default: '' 103 | - name: searchPatternPush 104 | type: string 105 | default: '$(Build.ArtifactStagingDirectory)/*.nupkg' 106 | # Global options 107 | - name: configuration # Set --configuration flag, e.g. configuration: Debug or configuration: Release 108 | type: string 109 | default: '' 110 | - name: outputDir 111 | type: string 112 | default: '$(Build.ArtifactStagingDirectory)' 113 | - name: includeNuGetOrg 114 | type: boolean 115 | default: true 116 | - name: externalEndpoints 117 | type: string 118 | default: '' 119 | 120 | steps: 121 | - template: ../preSteps.yaml 122 | parameters: 123 | clean: ${{ parameters.clean }} 124 | checkout: ${{ parameters.checkout }} 125 | submodules: ${{ parameters.submodules }} 126 | download: ${{ parameters.download }} 127 | artifact: ${{ parameters.downloadArtifact }} 128 | preSteps: ${{ parameters.preSteps }} 129 | - ${{ if parameters.version }}: 130 | - task: UseDotNet@2 131 | displayName: 'Use dotNet ${{ parameters.packageType }} ${{ parameters.version }}' 132 | inputs: 133 | packageType: ${{ parameters.packageType }} 134 | version: ${{ parameters.version }} 135 | - ${{ if in(parameters.command, 'build', 'publish', 'restore') }}: 136 | - task: DotNetCoreCLI@2 137 | displayName: 'dotNet restore ${{ parameters.projects }}' 138 | inputs: 139 | command: restore 140 | projects: '${{ parameters.projects }}' 141 | includeNuGetOrg: ${{ parameters.includeNuGetOrg }} 142 | ${{ if parameters.nugetConfigPath }}: 143 | feedsToUse: config 144 | nugetConfigPath: ${{ parameters.nugetConfigPath }} 145 | ${{ if and(parameters.feedRestore, not(parameters.nugetConfigPath)) }}: 146 | feedsToUse: select 147 | feedRestore: '${{ parameters.feedRestore }}' 148 | ${{ if parameters.externalEndpoints }}: 149 | externalEndpoints: ${{ parameters.externalEndpoints }} 150 | - ${{ if in(parameters.command, 'build', 'publish') }}: 151 | - task: DotNetCoreCLI@2 152 | displayName: 'dotNet ${{ parameters.command }} ${{ parameters.projects }}' 153 | inputs: 154 | command: ${{ parameters.command }} 155 | projects: '${{ parameters.projects }}' 156 | ${{ if parameters.configuration }}: 157 | arguments: --no-restore --configuration ${{ parameters.configuration }} --output ${{ parameters.outputDir }} ${{ parameters.arguments }}' 158 | ${{ if not(parameters.configuration) }}: 159 | arguments: --no-restore --output ${{ parameters.outputDir }} ${{ parameters.arguments }}' 160 | ${{ if eq(parameters.command, 'publish') }}: 161 | publishWebProjects: '${{ parameters.publishWebProjects }}' 162 | - ${{ if parameters.searchPatternPack }}: 163 | - task: DotNetCoreCLI@2 164 | displayName: 'dotNet pack ${{ parameters.searchPatternPack }}' 165 | inputs: 166 | command: pack 167 | searchPatternPack: '${{ parameters.searchPatternPack }}' 168 | ${{ if parameters.configuration }}: 169 | configuration: '${{ parameters.configuration }}' 170 | outputDir: '${{ parameters.outputDir }}' 171 | includesymbols: '${{ parameters.includeSymbols }}' 172 | versioningScheme: '${{ parameters.versioningScheme }}' 173 | ${{ if eq(parameters.versioningScheme, 'byEnvVar') }}: 174 | versionEnvVar: '${{ parameters.versionEnvVar }}' 175 | ${{ if eq(parameters.versioningScheme, 'ByPrereleaseNumber') }}: 176 | majorVersion: ${{ parameters.majorVersion }} 177 | minorVersion: ${{ parameters.minorVersion }} 178 | patchVersion: ${{ parameters.patchVersion }} 179 | includeNuGetOrg: ${{ parameters.includeNuGetOrg }} 180 | ${{ if parameters.nugetConfigPath }}: 181 | feedsToUse: config 182 | nugetConfigPath: ${{ parameters.nugetConfigPath }} 183 | ${{ if and(parameters.feedRestore, not(parameters.nugetConfigPath)) }}: 184 | feedsToUse: select 185 | feedRestore: '${{ parameters.feedRestore }}' 186 | ${{ if parameters.externalEndpoints }}: 187 | externalEndpoints: ${{ parameters.externalEndpoints }} 188 | - ${{ if parameters.publishSymbols }}: 189 | - task: PublishSymbols@2 190 | displayName: 'Publish Symbols Path' 191 | inputs: 192 | SearchPattern: '${{ parameters.outputDir }}/*.pdb' 193 | publishSymbols: true 194 | SymbolServerType: TeamServices 195 | - ${{ if and(parameters.push, or(parameters.externalEndpoints, parameters.feedPublish)) }}: 196 | - task: DotNetCoreCLI@2 197 | displayName: 'dotNet Push NuGet' 198 | inputs: 199 | command: push 200 | searchPatternPush: '${{ parameters.searchPatternPush }}' 201 | ${{ if and(parameters.feedPublish, not(parameters.externalEndpoints)) }}: 202 | feedPublish: '${{ parameters.feedPublish }}' 203 | nuGetFeedType: internal 204 | ${{ if and(parameters.externalEndpoints, not(parameters.feedPublish)) }}: 205 | externalEndpoints: ${{ parameters.externalEndpoints }} 206 | nuGetFeedType: external 207 | - template: ../postSteps.yaml 208 | parameters: 209 | postSteps: ${{ parameters.postSteps }} 210 | ${{ if and(parameters.publishEnabled, in(parameters.command, 'build', 'publish')) }}: 211 | artifact: '${{ parameters.publishArtifact }}' 212 | publish: '${{ parameters.outputDir }}' 213 | clean: ${{ parameters.clean }} 214 | -------------------------------------------------------------------------------- /steps/build/helmTemplate.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | - name: downloadPath 22 | type: string 23 | default: '' 24 | # postSteps 25 | - name: postSteps 26 | type: stepList 27 | default: [] 28 | - name: publishEnabled 29 | type: boolean 30 | default: true 31 | - name: artifactName 32 | type: string 33 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)' 34 | # Helm Installer 35 | - name: helmVersion 36 | type: string 37 | default: '3.1.3' 38 | - name: kubectlVersion 39 | type: string 40 | default: '1.18.6' 41 | # Helm Deploy add and update repo 42 | - name: repoName 43 | type: string 44 | default: '' 45 | - name: repoURL 46 | type: string 47 | default: '' 48 | # Render Helm Chart params 49 | - name: replaceTokens # Enable replace tokens task for targets 50 | type: boolean 51 | default: false 52 | - name: replaceTokensTargets # Replace tokens in chart and values file 53 | type: object 54 | default: | 55 | **/*.yaml 56 | - name: namespace 57 | type: string 58 | default: '' 59 | - name: helmReleaseName 60 | type: string 61 | default: '$(Build.DefinitionName)' 62 | - name: helmChartPath # Root path of helm charts 63 | type: string 64 | default: '$(Build.Repository.LocalPath)' 65 | - name: helmValueFile # File path to values 66 | type: string 67 | default: '$(Build.Repository.LocalPath)/values.yaml' 68 | - name: helmChartVersion 69 | type: string 70 | default: '$(Build.BuildNumber)' 71 | - name: helmArguments # Additional args for helm template command 72 | type: string 73 | default: '' 74 | - name: outputDir # Output dir for helm template command 75 | type: string 76 | default: '$(Pipeline.Workspace)/helmTemplate' 77 | 78 | steps: 79 | - template: ../preSteps.yaml 80 | parameters: 81 | clean: ${{ parameters.clean }} 82 | checkout: ${{ parameters.checkout }} 83 | submodules: ${{ parameters.submodules }} 84 | download: ${{ parameters.download }} 85 | artifact: ${{ parameters.downloadArtifact }} 86 | preSteps: ${{ parameters.preSteps }} 87 | # Helm Installer 88 | - ${{ if and(parameters.helmVersion, parameters.kubectlVersion) }}: 89 | - task: HelmInstaller@0 90 | displayName: 'Install Helm ${{ parameters.helmVersion }} and Kubectl ${{ parameters.kubectlVersion }}' 91 | inputs: 92 | helmVersion: '${{ parameters.helmVersion }}' 93 | checkLatestHelmVersion: false 94 | kubectlVersion: '${{ parameters.kubectlVersion }}' 95 | checkLatestKubectl: false 96 | # Helm Deploy add and update repo 97 | - ${{ if and(parameters.repoName, parameters.repoURL) }}: 98 | - task: HelmDeploy@0 99 | displayName: 'Add ${{ parameters.repoName }} Helm Repo' 100 | inputs: 101 | connectionType: None 102 | command: repo 103 | arguments: 'add ${{ parameters.repoName }} ${{ parameters.repoURL }}' 104 | - task: HelmDeploy@0 105 | displayName: 'Update Helm Repos' 106 | inputs: 107 | connectionType: None 108 | command: repo 109 | arguments: update 110 | # Replace Tokens in Helm Charts 111 | - ${{ if and(parameters.helmReleaseName, parameters.helmChartPath, parameters.helmValueFile, parameters.helmChartVersion) }}: 112 | - ${{ if parameters.replaceTokens }}: 113 | - task: replacetokens@3 114 | displayName: 'Replace tokens in Helm Charts' 115 | inputs: 116 | rootDirectory: '${{ parameters.helmChartPath }}' 117 | targetFiles: ${{ parameters.replaceTokensTargets }} 118 | encoding: 'auto' 119 | writeBOM: true 120 | actionOnMissing: 'warn' 121 | keepToken: false 122 | tokenPrefix: '#{' 123 | tokenSuffix: '}#' 124 | useLegacyPattern: false 125 | enableTelemetry: false 126 | # Render Helm Chart into Kubernetes Manifests 127 | - ${{ if parameters.namespace }}: 128 | - bash: | 129 | kubectl config set-context --current --namespace ${{ parameters.namespace }} 130 | displayName: 'Kubernetes namespace: ${{ parameters.namespace }}' 131 | - ${{ if parameters.helmArguments }}: 132 | - bash: | 133 | helm template ${{ parameters.helmReleaseName }} ${{ parameters.helmChartPath }} \ 134 | --namespace ${{ parameters.namespace }} \ 135 | --values ${{ parameters.helmValueFile }} \ 136 | --output-dir ${{ parameters.outputDir }} \ 137 | --version ${{ parameters.helmChartVersion }} \ 138 | --include-crds \ 139 | ${{ parameters.helmArguments }} 140 | displayName: 'Render Helm Charts' 141 | - ${{ if not(parameters.helmArguments) }}: 142 | - bash: | 143 | helm template ${{ parameters.helmReleaseName }} ${{ parameters.helmChartPath }} \ 144 | --namespace ${{ parameters.namespace }} \ 145 | --values ${{ parameters.helmValueFile }} \ 146 | --output-dir ${{ parameters.outputDir }} \ 147 | --version ${{ parameters.helmChartVersion }} \ 148 | --include-crds 149 | displayName: 'Render Helm Charts' 150 | - template: ../postSteps.yaml 151 | parameters: 152 | postSteps: ${{ parameters.postSteps }} 153 | ${{ if parameters.publishEnabled }}: 154 | publish: '${{ parameters.outputDir }}' 155 | artifact: '${{ parameters.artifactName }}' 156 | clean: ${{ parameters.clean }} 157 | -------------------------------------------------------------------------------- /steps/build/nugetPackage.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | # postSteps 22 | - name: postSteps 23 | type: stepList 24 | default: [] 25 | - name: publishArtifact 26 | type: string 27 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)' 28 | - name: publishEnabled # Publish a pipeline artifact of build and pack outputDir 29 | type: boolean 30 | default: true 31 | # dotNet type and version 32 | - name: packageType 33 | type: string 34 | default: sdk 35 | values: 36 | - sdk 37 | - runtime 38 | - name: version 39 | type: string 40 | default: '' 41 | # dotNet Restore and Build 42 | - name: projects # Optional file match pattern to build or publish projects 43 | type: string 44 | default: '' 45 | - name: command 46 | type: string 47 | default: build 48 | values: 49 | - build 50 | - publish 51 | - name: arguments 52 | type: string 53 | default: '' 54 | - name: feedRestore # feed for dotNet restore 55 | type: string 56 | default: '' 57 | - name: externalEndpoints 58 | type: string 59 | default: '' 60 | - name: includeNuGetOrg 61 | type: boolean 62 | default: true 63 | # dotNet Pack 64 | - name: searchPatternPack # Required to enable pack. Pattern to search for csproj or nuspec files. Separate multiple patterns with semicolon. Exclude patterns with a ! prefix e.g. **/*.csproj;!**/*.Tests.csproj 65 | type: string 66 | default: '' 67 | - name: searchPatternPush # enables dotNet push after dotNet pack 68 | type: string 69 | default: '$(Build.ArtifactStagingDirectory)/*.nupkg' 70 | - name: feedPublish # dotNet push feed to publish of dotNet pack output NuGet package 71 | type: string 72 | default: '' 73 | - name: includeSymbols # dotNet pack includeSymbols 74 | type: boolean 75 | default: false 76 | - name: publishSymbols # Enable Publish Symbols task after dotNet pack 77 | type: boolean 78 | default: false 79 | - name: versioningScheme # byEnvVar is default, set value or EnvVar 80 | type: string 81 | default: byEnvVar 82 | values: 83 | - off 84 | - byPrereleaseNumber 85 | - byEnvVar 86 | - byBuildNumber 87 | - name: versionEnvVar # Name of environment variable to use for version number 88 | type: string 89 | default: NugetVersion 90 | - name: majorVersion # Required when versioningScheme is byPrereleaseNumber 91 | type: number 92 | default: 1 93 | - name: minorVersion # Required when versioningScheme is byPrereleaseNumber 94 | type: number 95 | default: 0 96 | - name: patchVersion # Required when versioningScheme is byPrereleaseNumber 97 | type: number 98 | default: 0 99 | # dotNet Restore, Build, Publish, Pack, and Push 100 | - name: configuration 101 | type: string 102 | default: Release 103 | - name: outputDir 104 | type: string 105 | default: '$(Build.ArtifactStagingDirectory)' 106 | 107 | steps: 108 | - template: ../preSteps.yaml 109 | parameters: 110 | clean: ${{ parameters.clean }} 111 | checkout: ${{ parameters.checkout }} 112 | submodules: ${{ parameters.submodules }} 113 | download: ${{ parameters.download }} 114 | artifact: ${{ parameters.downloadArtifact }} 115 | preSteps: ${{ parameters.preSteps }} 116 | - ${{ if parameters.projects }}: 117 | - template: dotNetCore.yaml 118 | parameters: 119 | clean: false 120 | checkout: false 121 | download: false 122 | packageType: ${{ parameters.packageType }} 123 | version: ${{ parameters.version }} 124 | command: ${{ parameters.command }} 125 | configuration: ${{ parameters.configuration }} 126 | projects: ${{ parameters.projects }} 127 | arguments: ${{ parameters.arguments}} 128 | feedRestore: ${{ parameters.feedRestore }} 129 | outputDir: ${{ parameters.outputDir }} 130 | publishEnabled: false 131 | - ${{ if parameters.searchPatternPack }}: 132 | - template: dotNetCore.yaml 133 | parameters: 134 | clean: false 135 | checkout: false 136 | download: false 137 | version: '' 138 | searchPatternPack: ${{ parameters.searchPatternPack }} 139 | searchPatternPush: '${{ parameters.searchPatternPush }}' 140 | configuration: ${{ parameters.configuration }} 141 | feedRestore: ${{ parameters.feedRestore }} 142 | feedPublish: ${{ parameters.feedPublish }} 143 | externalEndpoints: ${{ parameters.externalEndpoints }} 144 | includeSymbols: ${{ parameters.includeSymbols }} 145 | publishSymbols: ${{ parameters.publishSymbols }} 146 | versioningScheme: ${{ parameters.versioningScheme }} 147 | versionEnvVar: ${{ parameters.versionEnvVar }} 148 | majorVersion: ${{ parameters.majorVersion }} 149 | minorVersion: ${{ parameters.minorVersion }} 150 | patchVersion: ${{ parameters.patchVersion }} 151 | outputDir: ${{ parameters.outputDir }} 152 | publishEnabled: false 153 | - template: ../postSteps.yaml 154 | parameters: 155 | postSteps: ${{ parameters.postSteps }} 156 | ${{ if parameters.publishEnabled }}: 157 | artifact: '${{ parameters.publishArtifact }}' 158 | publish: '${{ parameters.outputDir }}' 159 | clean: ${{ parameters.clean }} 160 | -------------------------------------------------------------------------------- /steps/code/dotNetTests.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | # postSteps 22 | - name: postSteps 23 | type: stepList 24 | default: [] 25 | - name: publish 26 | type: string 27 | default: '$(Agent.TempDirectory)' 28 | - name: publishArtifact 29 | type: string 30 | default: '$(Build.DefinitionName)_$(System.JobName)' 31 | # Use dotNet 32 | - name: packageType 33 | type: string 34 | default: sdk 35 | values: 36 | - sdk 37 | - runtime 38 | - name: version # Optional dotNet version string to enable use dotNet task 39 | type: string 40 | default: '' 41 | - name: feedRestore # dotNet restore using NuGet feed to restore 42 | type: string 43 | default: '' 44 | # dotNet Test Tasks for each test in tests 45 | - name: tests # Inserts dotnet test for each item in list, project key required 46 | type: object 47 | default: 48 | - projects: '***[Uu]nit.[Tt]est*.csproj' # Pattern search for unit test projects 49 | arguments: '--collect "Code Coverage" /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Common.TestResultsDirectory)\Coverage\' 50 | displayName: 'dotNet Unit Tests' 51 | testRunTitle: 'Unit Tests' # Optional, if task displayName is different than testRunTitle 52 | - name: publishTestResults #Enabling this option will generate a test results TRX file in $(Agent.TempDirectory) and results will be published to the server. This option appends --logger trx --results-directory $(Agent.TempDirectory) to the command line arguments. 53 | type: boolean 54 | default: true 55 | 56 | steps: 57 | - template: ../preSteps.yaml 58 | parameters: 59 | clean: ${{ parameters.clean }} 60 | checkout: ${{ parameters.checkout }} 61 | submodules: ${{ parameters.submodules }} 62 | download: ${{ parameters.download }} 63 | artifact: ${{ parameters.downloadArtifact }} 64 | preSteps: ${{ parameters.preSteps }} 65 | - ${{ if gt(length(parameters.tests), 0) }}: 66 | - ${{ each test in parameters.tests }}: 67 | - ${{ if test.projects }}: 68 | - template: ../build/dotNetCore.yaml 69 | parameters: 70 | clean: false 71 | checkout: false 72 | download: false 73 | command: restore 74 | packageType: ${{ parameters.packageType }} 75 | version: ${{ parameters.version }} 76 | projects: ${{ parameters.projects }} 77 | feedRestore: ${{ parameters.feedRestore }} 78 | - task: DotNetCoreCLI@2 79 | ${{ if test.displayName }}: 80 | displayName: ${{ test.displayName }} 81 | ${{ if not(test.displayName) }}: 82 | displayName: 'dotNet Test ${{ test.projects }}' 83 | inputs: 84 | command: test 85 | projects: '${{ test.projects }}' 86 | ${{ if test.arguments }}: 87 | arguments: '${{ test.arguments }}' 88 | ${{ if not(test.arguments) }}: 89 | arguments: '--collect "Code Coverage"' 90 | ${{ if test.publishTestResults }}: 91 | publishTestResults: true 92 | ${{ if and(eq(test.publishTestResults, ''), parameters.publishTestResults) }}: 93 | publishTestResults: true 94 | ${{ if test.testRunTitle }}: 95 | testRunTitle: ${{ test.testRunTitle }} 96 | ${{ if and(not(test.testRunTitle), test.displayName) }}: 97 | testRunTitle: ${{ test.displayName }} 98 | - template: ../postSteps.yaml 99 | parameters: 100 | postSteps: ${{ parameters.postSteps }} 101 | publish: ${{ parameters.publish }} 102 | artifact: ${{ parameters.publishArtifact }} 103 | clean: ${{ parameters.clean }} 104 | -------------------------------------------------------------------------------- /steps/code/sonarQube.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | # postSteps 22 | - name: postSteps 23 | type: stepList 24 | default: [] 25 | - name: publishArtifact # Set artifact name to enable publish artifacts from parameters.outputDir 26 | type: string 27 | default: '' 28 | # Use dotNet 29 | - name: dotNetType 30 | type: string 31 | default: sdk 32 | values: 33 | - sdk 34 | - runtime 35 | - name: dotNetVersion 36 | type: string 37 | default: '' 38 | # dotNet Build and Restore Params 39 | - name: dotNetProjects # dotNet projects or vs solution for dotNet build and restore 40 | type: string 41 | - name: dotNetFeedRestore # default dotNet artifact feed 42 | type: string 43 | default: '' 44 | - name: dotNetArguments # default dotNet build arguments 45 | type: string 46 | default: '' 47 | - name: dotNetCommand 48 | type: string 49 | default: build 50 | values: 51 | - restore 52 | - build 53 | - publish 54 | - name: outputDir 55 | type: string 56 | default: '$(Build.ArtifactStagingDirectory)' 57 | # SonarQube Prepare 58 | - name: sonarCloud # Use instead of parameters.sonarQube when using SonarCloud instead of self hosted, this is the service connection name. 59 | type: string 60 | default: '' 61 | - name: organization # Required when using SonarCloud instead of SonarQube 62 | type: string 63 | default: '' 64 | - name: sonarQube # SonarQube Service Connection Name 65 | type: string 66 | default: '' 67 | - name: scannerMode 68 | type: string 69 | default: MSBuild 70 | values: 71 | - MSBuild 72 | - CLI 73 | - Other 74 | - name: configFile # More information is available at http://redirect.sonarsource.com/doc/install-configure-scanner-tfs-ts.html 75 | type: string 76 | default: '' 77 | - name: projectKey # MSBuild or CLI project Key. The SonarQube project unique key, i.e. 'sonar.projectKey' 78 | type: string 79 | default: '' 80 | - name: projectName # The SonarQube project name, i.e. 'sonar.projectName' 81 | type: string 82 | default: '' 83 | - name: projectVersion # The SonarQube project version, i.e. 'sonar.projectVersion' 84 | type: string 85 | default: '$(Build.BuildId)' 86 | - name: extraProperties # Additional properties that will be passed to the scanner, \n# Put one key=value per line, example:\n# sonar.exclusions=**/*.bin 87 | type: string 88 | default: 'sonar.coverage.exclusions=**/**Tests*.cs,**/**Wrapper*.cs,**/**Façade*.cs,**/**Creator*.cs,**/**Program.cs' 89 | - name: cliSources # Path to the root directory containing source files. This value is set to the 'sonar.sources' SonarQube property 90 | type: string 91 | default: '$(Build.Repository.LocalPath)' 92 | # SonarQube Analyze and Publish 93 | - name: sonarQubeAnalyze # True inserts the SonarQubeAnalyze task 94 | type: boolean 95 | default: true 96 | - name: sonarQubePublish # True inserts the SonarQubePublish task 97 | type: boolean 98 | default: true 99 | - name: pollingTimeoutSec 100 | type: number 101 | default: 300 102 | 103 | steps: 104 | - template: ../preSteps.yaml 105 | parameters: 106 | clean: ${{ parameters.clean }} 107 | checkout: ${{ parameters.checkout }} 108 | submodules: ${{ parameters.submodules }} 109 | download: ${{ parameters.download }} 110 | artifact: ${{ parameters.downloadArtifact }} 111 | preSteps: ${{ parameters.preSteps }} 112 | - ${{ if parameters.sonarQube }}: 113 | - task: SonarQubePrepare@4 114 | displayName: 'Prepare analysis with SonarQube' 115 | inputs: 116 | SonarQube: '${{ parameters.sonarQube }}' 117 | scannerMode: '${{ parameters.scannerMode }}' 118 | extraProperties: '${{ parameters.extraProperties }}' 119 | ${{ if eq(parameters.scannerMode, 'MSBuild') }}: 120 | projectKey: '${{ parameters.projectKey }}' 121 | projectName: '${{ parameters.projectName }}' 122 | projectVersion: '${{ parameters.projectVersion }}' 123 | ${{ if eq(parameters.scannerMode, 'CLI') }}: 124 | ${{ if parameters.configFile }}: 125 | configMode: file 126 | configFile: ${{ parameters.configFile }} 127 | ${{ if not(parameters.configFile) }}: 128 | configMode: manual 129 | cliProjectKey: '${{ parameters.projectKey }}' 130 | cliProjectName: '${{ parameters.projectName }}' 131 | cliProjectVersion: '${{ parameters.projectVersion }}' 132 | cliSources: '${{ parameters.cliSources }}' 133 | - ${{ if parameters.sonarCloud }}: 134 | - task: SonarCloudPrepare@1 135 | displayName: 'Prepare analysis with SonarCloud' 136 | inputs: 137 | SonarCloud: '${{ parameters.sonarCloud }}' 138 | organization: '${{ parameters.organization }}' 139 | scannerMode: '${{ parameters.scannerMode }}' 140 | extraProperties: '${{ parameters.extraProperties }}' 141 | ${{ if eq(parameters.scannerMode, 'MSBuild') }}: 142 | projectKey: '${{ parameters.projectKey }}' 143 | projectName: '${{ parameters.projectName }}' 144 | projectVersion: '${{ parameters.projectVersion }}' 145 | ${{ if eq(parameters.scannerMode, 'CLI') }}: 146 | ${{ if parameters.configFile }}: 147 | configMode: file 148 | configFile: ${{ parameters.configFile }} 149 | ${{ if not(parameters.configFile) }}: 150 | configMode: manual 151 | cliProjectKey: '${{ parameters.projectKey }}' 152 | cliProjectName: '${{ parameters.projectName }}' 153 | cliProjectVersion: '${{ parameters.projectVersion }}' 154 | cliSources: '${{ parameters.cliSources }}' 155 | - ${{ if parameters.dotNetProjects }}: 156 | - template: ../build/dotNetCore.yaml 157 | parameters: 158 | clean: false 159 | checkout: false 160 | download: false 161 | command: ${{ parameters.dotNetCommand }} 162 | packageType: ${{ parameters.dotNetType }} 163 | version: ${{ parameters.dotNetVersion }} 164 | projects: ${{ parameters.dotNetProjects }} 165 | feedRestore: ${{ parameters.dotNetFeedRestore }} 166 | arguments: ${{ parameters.dotNetArguments }} 167 | outputDir: ${{ parameters.dotNetOutput }} 168 | - ${{ if parameters.sonarQube }}: 169 | - ${{ if parameters.sonarQubeAnalyze }}: 170 | - task: SonarQubeAnalyze@4 171 | displayName: 'Run SonarQube Analysis' 172 | - ${{ if parameters.sonarQubePublish }}: 173 | - task: SonarQubePublish@4 174 | displayName: 'Publish SonarQube Quality Gate Result' 175 | inputs: 176 | pollingTimeoutSec: '${{ parameters.pollingTimeoutSec }}' 177 | - ${{ if parameters.sonarCloud }}: 178 | - ${{ if parameters.sonarQubeAnalyze }}: 179 | - task: SonarCloudAnalyze@1 180 | displayName: 'Run SonarQube Analysis' 181 | - ${{ if parameters.sonarQubePublish }}: 182 | - task: SonarCloudPublish@1 183 | displayName: 'Publish SonarQube Quality Gate Result' 184 | inputs: 185 | pollingTimeoutSec: '${{ parameters.pollingTimeoutSec }}' 186 | - template: ../postSteps.yaml 187 | parameters: 188 | postSteps: ${{ parameters.postSteps }} 189 | ${{ if parameters.publishArtifact }}: 190 | publish: ${{ parameters.outputDir }} 191 | artifact: ${{ parameters.publishArtifact }} 192 | clean: ${{ parameters.clean }} 193 | -------------------------------------------------------------------------------- /steps/deploy/armTemplate.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | - name: replaceTokens # Enable replace tokens task 22 | type: boolean 23 | default: false 24 | # postSteps 25 | - name: postSteps 26 | type: stepList 27 | default: [] 28 | - name: publishArtifact 29 | type: string 30 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)' 31 | - name: publishEnabled 32 | type: boolean 33 | default: false 34 | # Deploy AzureRM Template Params 35 | - name: azureSubscription # Service connection to subscription for the resource group 36 | type: string 37 | default: '' 38 | - name: azureLocation # If the resource group already exists in the subscription, then this value will be ignored. 39 | type: string 40 | default: '' 41 | - name: resourceGroupName 42 | type: string 43 | default: '' 44 | - name: templateFile # File name of template 45 | type: string 46 | default: '' 47 | - name: templatePath # Root path to template 48 | type: string 49 | default: '$(Build.Repository.LocalPath)' 50 | - name: parametersFile # Parameters File 51 | type: string 52 | default: '' 53 | - name: overrideParameters # Parameters Overrides 54 | type: string 55 | default: '' 56 | - name: deploymentCleanup # Enable cleanup previous ARM deployments script 57 | type: boolean 58 | default: false 59 | - name: deploymentCleanupSkip # Azure by default limits to 800 deployments to a group. This will remove the last one so that the deployment is not blocked 60 | type: number 61 | default: 799 62 | - name: deploymentMode # Incremental mode handles deployments as incremental updates to the resource group. It leaves unchanged resources that exist in the resource group but are not specified in the template. Complete mode deletes resources that are not in your template. Validate mode enables you to find problems with the template before creating actual resources. 63 | type: string 64 | default: Incremental 65 | values: 66 | - Incremental 67 | - Complete 68 | - Validation 69 | - name: action # Action to be performed on the Azure resources or resource group. 70 | type: string 71 | default: Create Or Update Resource Group 72 | values: 73 | - Create Or Update Resource Group 74 | - Select Resource Group 75 | - Start 76 | - Stop 77 | - StopWithDeallocate 78 | - Restart 79 | - Delete 80 | - DeleteRG 81 | 82 | steps: 83 | - template: ../preSteps.yaml 84 | parameters: 85 | clean: ${{ parameters.clean }} 86 | checkout: ${{ parameters.checkout }} 87 | submodules: ${{ parameters.submodules }} 88 | download: ${{ parameters.download }} 89 | artifact: ${{ parameters.downloadArtifact }} 90 | preSteps: ${{ parameters.preSteps }} 91 | - ${{ if and(parameters.azureSubscription, parameters.resourceGroupName) }}: 92 | - ${{ if parameters.deploymentCleanup }}: 93 | - task: AzurePowerShell@5 94 | displayName: 'Cleanup Previous AzureRM Deployments' 95 | inputs: 96 | azureSubscription: '${{ parameters.azureSubscription }}' 97 | ScriptType: InlineScript 98 | pwsh: true 99 | Inline: Get-AzResourceGroupDeployment -ResourceGroupName ${{ parameters.resourceGroupName }} | Select-Object -Skip ${{ parameters.deploymentCleanupSkip }} | foreach-object { Start-Job -InputObject $_ -ScriptBlock { $input | Remove-AzResourceGroupDeployment } } 100 | azurePowerShellVersion: latestVersion 101 | - ${{ if parameters.replaceTokens }}: 102 | - task: replacetokens@3 103 | displayName: 'Replace Tokens in ${{ parameters.templatePath }}' 104 | inputs: 105 | rootDirectory: '${{ parameters.templatePath }}' 106 | targetFiles: '*.json' 107 | - task: AzureResourceGroupDeployment@2 108 | displayName: 'Deploy AzureRM Template ${{ parameters.templateFile }}' 109 | inputs: 110 | azureSubscription: '${{ parameters.azureSubscription }}' 111 | resourceGroupName: '${{ parameters.resourceGroupName }}' 112 | deploymentMode: '${{ parameters.deploymentMode }}' 113 | action: '${{ parameters.action }}' 114 | ${{ if and(eq(parameters.action, 'Create Or Update Resource Group'), parameters.azureLocation) }}: 115 | location: '${{ parameters.azureLocation }}' 116 | ${{ if parameters.templateFile }}: 117 | csmFile: '${{ parameters.templatePath }}/${{ parameters.templateFile }}' 118 | ${{ if parameters.parametersFile }}: 119 | csmParametersFile: '${{ parameters.templatePath }}/${{ parameters.parametersFile }}' 120 | ${{ if parameters.overrideParameters }}: 121 | overrideParameters: '${{ parameters.overrideParameters }}' 122 | - template: ../postSteps.yaml 123 | parameters: 124 | postSteps: ${{ parameters.postSteps }} 125 | ${{ if parameters.publishEnabled }}: 126 | publish: '${{ parameters.templatePath }}' 127 | artifact: '${{ parameters.publishArtifact }}' 128 | clean: ${{ parameters.clean }} 129 | -------------------------------------------------------------------------------- /steps/deploy/helmChart.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: none 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | - name: replaceTokens # Enable replace tokens task 22 | type: boolean 23 | default: false 24 | - name: replaceTokensTargets # Replace tokens in chart and values file 25 | type: object 26 | default: | 27 | **/*.yaml 28 | # postSteps 29 | - name: postSteps 30 | type: stepList 31 | default: [] 32 | - name: artifactName 33 | type: string 34 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)' 35 | # Get Azure KeyVault Params 36 | - name: keyVaultSubscription 37 | type: string 38 | default: '' 39 | - name: keyVaultName 40 | type: string 41 | default: '' 42 | - name: keyVaultSecretFilter 43 | type: string 44 | default: '*' 45 | # Helm Installer 46 | - name: helmVersion 47 | type: string 48 | default: '3.1.3' 49 | - name: kubectlVersion 50 | type: string 51 | default: '1.18.6' 52 | # Create imagePullSecret 53 | - name: dockerRegistryEndpoint # Required to enable task. Service connection name to container registry 54 | type: string 55 | default: '' 56 | - name: imagePullSecret # Required to enable task. Name of secret to create in Kubernetes 57 | type: string 58 | default: '' 59 | # Helm Deploy 60 | - name: enableHelmDeploy 61 | type: boolean 62 | default: true 63 | - name: kubernetesServiceConnection # Use either environmentResource or kubernetesServiceConnection 64 | type: string 65 | default: '' 66 | - name: namespace # Required param for kube namespace 67 | type: string 68 | - name: helmCommand # Helm deploy command 69 | type: string 70 | default: 'upgrade' 71 | - name: helmChartPath # Root path of helm charts 72 | type: string 73 | default: '$(Build.Repository.LocalPath)' 74 | - name: helmReleaseName 75 | type: string 76 | default: '$(Build.DefinitionName)' 77 | - name: helmOverrideValues 78 | type: string 79 | default: '' 80 | - name: helmValueFile # File path to values 81 | type: string 82 | default: '$(Build.Repository.LocalPath)/values.yaml' 83 | - name: helmInstall # When command is upgrade install if not already done 84 | type: boolean 85 | default: true 86 | - name: helmForce 87 | type: boolean 88 | default: true 89 | - name: helmResetValues 90 | type: boolean 91 | default: false 92 | - name: helmWaitForExecution 93 | type: boolean 94 | default: true 95 | - name: helmFailOnStderr 96 | type: boolean 97 | default: false 98 | # Archive Helm Charts and Pipeline Publish 99 | - name: archiveArtifacts 100 | type: boolean 101 | default: false 102 | - name: archiveFile 103 | type: string 104 | default: '$(Pipeline.Workspace)/HelmCharts' 105 | - name: archiveType 106 | type: string 107 | default: 'zip' 108 | values: 109 | - 'tar.gz' 110 | - 'zip' 111 | 112 | steps: 113 | - template: ../preSteps.yaml 114 | parameters: 115 | clean: ${{ parameters.clean }} 116 | checkout: ${{ parameters.checkout }} 117 | submodules: ${{ parameters.submodules }} 118 | download: ${{ parameters.download }} 119 | artifact: ${{ parameters.downloadArtifact }} 120 | preSteps: ${{ parameters.preSteps }} 121 | - ${{ if parameters.keyVaultName }}: 122 | - task: AzureKeyVault@1 123 | displayName: 'Get Azure Key Vault ${{ parameters.keyVaultName }}' 124 | inputs: 125 | azureSubscription: '${{ parameters.keyVaultSubscription }}' 126 | KeyVaultName: '${{ parameters.keyVaultName }}' 127 | SecretsFilter: '${{ parameters.keyVaultSecretFilter }}' 128 | - ${{ if parameters.replaceTokens }}: 129 | - task: replacetokens@3 130 | displayName: 'Replace tokens in Helm Charts' 131 | inputs: 132 | rootDirectory: '${{ parameters.helmChartPath }}' 133 | targetFiles: ${{ parameters.replaceTokensTargets }} 134 | encoding: 'auto' 135 | writeBOM: true 136 | actionOnMissing: 'warn' 137 | keepToken: false 138 | tokenPrefix: '#{' 139 | tokenSuffix: '}#' 140 | useLegacyPattern: false 141 | enableTelemetry: false 142 | - ${{ if and(parameters.kubernetesServiceConnection, parameters.dockerRegistryEndpoint, parameters.imagePullSecret) }}: 143 | - task: KubernetesManifest@0 144 | displayName: 'Create imagePullSecret ${{ parameters.imagePullSecret }} in ${{ parameters.namespace }} namespace' 145 | inputs: 146 | action: createSecret 147 | secretType: dockerRegistry 148 | secretName: '${{ parameters.imagePullSecret }}' 149 | dockerRegistryEndpoint: '${{ parameters.dockerRegistryEndpoint }}' 150 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 151 | namespace: '${{ parameters.namespace }}' 152 | - ${{ if and(parameters.helmVersion, parameters.kubectlVersion) }}: 153 | - task: HelmInstaller@0 154 | displayName: 'Install Helm ${{ parameters.helmVersion }} and Kubectl ${{ parameters.kubectlVersion }}' 155 | inputs: 156 | helmVersion: '${{ parameters.helmVersion }}' 157 | checkLatestHelmVersion: false 158 | kubectlVersion: '${{ parameters.kubectlVersion }}' 159 | checkLatestKubectl: false 160 | - ${{ if parameters.enableHelmDeploy }}: 161 | - task: HelmDeploy@0 162 | displayName: 'Helm ${{ parameters.helmCommand }} of ${{ parameters.helmReleaseName }} in ${{ parameters.namespace }}' 163 | inputs: 164 | ${{ if parameters.kubernetesServiceConnection }}: 165 | connectionType: 'Kubernetes Service Connection' 166 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 167 | namespace: '${{ parameters.namespace }}' 168 | command: '${{ parameters.helmCommand }}' 169 | chartType: FilePath 170 | chartPath: '${{ parameters.helmChartPath }}' 171 | releaseName: '${{ parameters.helmReleaseName }}' 172 | overrideValues: '${{ parameters.helmOverrideValues }}' 173 | valueFile: '${{ parameters.helmValueFile }}' 174 | install: '${{ parameters.helmInstall }}' 175 | force: '${{ parameters.helmForce }}' 176 | recreate: false 177 | resetValues: '${{ parameters.helmResetValues }}' 178 | waitForExecution: '${{ parameters.helmWaitForExecution }}' 179 | failOnStderr: '${{ parameters.helmFailOnStderr }}' 180 | - ${{ if parameters.archiveArtifacts }}: 181 | - task: ArchiveFiles@2 182 | displayName: 'Archive Helm Chart Artifacts' 183 | inputs: 184 | rootFolderOrFile: '${{ parameters.helmChartPath }}' 185 | includeRootFolder: false 186 | archiveFile: '${{ parameters.archiveFile }}.${{ parameters.archiveType }}' 187 | ${{ if eq(parameters.archiveType, 'tar.gz') }}: 188 | archiveType: tar 189 | tarCompression: gz 190 | ${{ if eq(parameters.archiveType, 'zip') }}: 191 | archiveType: zip 192 | replaceExistingArchive: true 193 | - template: ../postSteps.yaml 194 | parameters: 195 | postSteps: ${{ parameters.postSteps }} 196 | ${{ if parameters.archiveArtifacts }}: 197 | publish: '${{ parameters.archiveFile }}.${{ parameters.archiveType }}' 198 | artifact: ${{ parameters.artifactName }} 199 | clean: ${{ parameters.clean }} 200 | -------------------------------------------------------------------------------- /steps/deploy/helmManifest.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: artifactName # projectFile or artifactName param required 19 | type: string 20 | default: '' 21 | # postSteps 22 | - name: postSteps 23 | type: stepList 24 | default: [] 25 | - name: publishEnabled # Publish artifact of manifests rendered from helm charts 26 | type: boolean 27 | default: false 28 | # Helm Installer 29 | - name: helmVersion 30 | type: string 31 | default: '3.1.3' 32 | - name: kubectlVersion 33 | type: string 34 | default: '1.18.6' 35 | # Helm Deploy add and update repo 36 | - name: repoName 37 | type: string 38 | default: '' 39 | - name: repoURL 40 | type: string 41 | default: '' 42 | # Render Helm Chart params 43 | - name: replaceTokens # Enable replace tokens task for targets 44 | type: boolean 45 | default: false 46 | - name: replaceTokensTargets # Replace tokens in chart and values file 47 | type: object 48 | default: | 49 | **/*.yaml 50 | - name: namespace 51 | type: string 52 | - name: helmReleaseName 53 | type: string 54 | default: '$(Build.DefinitionName)' 55 | - name: helmChartPath # Root path of helm charts 56 | type: string 57 | default: '$(Build.Repository.LocalPath)' 58 | - name: helmValueFile # File path to values 59 | type: string 60 | default: '$(Build.Repository.LocalPath)/values.yaml' 61 | - name: helmChartVersion 62 | type: string 63 | default: '$(Build.BuildNumber)' 64 | - name: helmArguments # Additional args for helm template command 65 | type: string 66 | default: '' 67 | - name: outputDir # Output dir for helm template command 68 | type: string 69 | default: '$(Pipeline.Workspace)/helmTemplate' 70 | # Deploy manifests from helm template outputs 71 | - name: kubeDeploy # Enable deployment of manifests 72 | type: boolean 73 | default: true 74 | - name: kubernetesServiceConnection # Service connection for kube deploy 75 | type: string 76 | default: '' 77 | 78 | steps: 79 | - template: ../preSteps.yaml 80 | parameters: 81 | clean: ${{ parameters.clean }} 82 | checkout: ${{ parameters.checkout }} 83 | submodules: ${{ parameters.submodules }} 84 | download: ${{ parameters.download }} 85 | artifact: ${{ parameters.artifactName }} 86 | preSteps: ${{ parameters.preSteps }} 87 | - template: ../build/helmTemplate.yaml 88 | parameters: 89 | clean: false 90 | checkout: false 91 | download: false 92 | publishEnabled: ${{ parameters.publishEnabled }} 93 | helmVersion: ${{ parameters.helmVersion }} 94 | kubectlVersion: ${{ parameters.kubectlVersion }} 95 | repoName: ${{ parameters.repoName }} 96 | repoURL: ${{ parameters.repoURL }} 97 | ${{ if parameters.replaceTokens }}: 98 | replaceTokens: true 99 | replaceTokensTargets: ${{ parameters.replaceTokensTargets }} 100 | namespace: ${{ parameters.namespace }} 101 | helmReleaseName: ${{ parameters.helmReleaseName }} 102 | helmChartPath: ${{ parameters.helmChartPath }} 103 | helmValueFile: ${{ parameters.helmValueFile }} 104 | helmChartVersion: ${{ parameters.helmChartVersion }} 105 | helmArguments: ${{ parameters.helmArguments }} 106 | outputDir: ${{ parameters.outputDir }} 107 | - ${{ if parameters.kubeDeploy }}: 108 | - template: kubeManifest.yaml 109 | parameters: 110 | clean: false 111 | checkout: false 112 | download: false 113 | kubernetesServiceConnection: ${{ parameters.kubernetesServiceConnection }} 114 | action: deploy 115 | strategy: '' 116 | manifests: '${{ parameters.outputDir }}/*' 117 | - template: ../postSteps.yaml 118 | parameters: 119 | postSteps: ${{ parameters.postSteps }} 120 | publish: '' 121 | artifact: '' 122 | clean: ${{ parameters.clean }} 123 | -------------------------------------------------------------------------------- /steps/deploy/kubeManifest.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: artifactName # Optional to set a specific artifact to download 19 | type: string 20 | default: '' 21 | # postSteps 22 | - name: postSteps 23 | type: stepList 24 | default: [] 25 | # Get Azure KeyVault Params 26 | - name: keyVaultSubscription 27 | type: string 28 | default: '' 29 | - name: keyVaultName 30 | type: string 31 | default: '' 32 | - name: keyVaultSecretFilter 33 | type: string 34 | default: '*' 35 | - name: secretArguments # Kube createSecret secretArguments for Azure KeyVault secrets 36 | type: object 37 | default: '' 38 | # Replace Tokens Task 39 | - name: replaceTokens # Enable replace tokens task for kube manifests 40 | type: boolean 41 | default: false 42 | - name: replaceTokensRoot # Enable replace tokens task for kube manifests 43 | type: string 44 | default: '$(Build.SourcesDirectory)' 45 | # Create imagePullSecret 46 | - name: dockerRegistryEndpoint # Required to enable task. Service connection name to container registry 47 | type: string 48 | default: '' 49 | - name: imagePullSecret # Required to enable task. Name of secret to create in Kubernetes 50 | type: string 51 | default: '' 52 | # Kube Deployment Params 53 | - name: kubectlVersion # Optional, inserts kube installer task with specific version 54 | type: string 55 | default: '' 56 | - name: kubernetesServiceConnection # Required for imagePullSecret create and deployment task. Except when using an ADO Environment Resource then it's not required for the deployment task 57 | type: string 58 | default: '' 59 | - name: namespace # Required, namespace in kubernetes cluster 60 | type: string 61 | default: default 62 | - name: manifests 63 | type: object 64 | default: '' 65 | - name: containers # Update the image tag of a container listed in a manifest spec. e.g. containers: registryURL/repoName/imageName:imageTag would look in the manifest and if it find registryURL/repoName/imageName and update the imageTag 66 | type: string 67 | default: '' 68 | - name: rolloutStatusTimeout # Used when action is deploy, promote, or reject 69 | type: number 70 | default: 60 71 | - name: strategy 72 | type: string 73 | default: '' # canary or null 74 | - name: percentage # Used when strategy is canary 75 | type: number 76 | default: 10 77 | - name: trafficSplitMethod # Used when strategy is canary 78 | type: string 79 | default: pod 80 | values: 81 | - smi 82 | - pod 83 | - name: baselineAndCanaryReplicas # Used when strategy is canary 84 | type: number 85 | default: 1 86 | - name: action # Default deploy; promote or reject prior canary kube deploy 87 | type: string 88 | default: deploy 89 | values: 90 | - deploy 91 | - promote 92 | - reject 93 | - scale 94 | - patch 95 | - delete 96 | # Bake Kubernetes Manifests 97 | - name: kustomizationPath # Optional to render Kustomization templates into Kube Manifests and deploy set this param 98 | type: string 99 | default: '' 100 | - name: helmChart # Optional to render helm Charts into Kube Manifests and deploy set this param. Only works with helm charts that contain no CRDs. If the helm chart has CRDs use the helmTemplate steps 101 | type: string 102 | default: '' 103 | - name: overrideFiles # Optional overridesFiles when using helmChart 104 | type: object 105 | default: '' 106 | - name: overrides # Optional overrides when using helmChart 107 | type: object 108 | default: '' 109 | - name: releaseName # Required releaseName when using helmChart 110 | type: string 111 | default: '' 112 | - name: dockerComposeFile # To render a docker compose file into a kube manifest and deploy 113 | type: string 114 | default: '' 115 | # Scale Kubernetes Deployments 116 | - name: kind # Required when action is scale or patch. The Kubernetes object kind 117 | type: string 118 | default: Deployment 119 | - name: name # Required when action is scale or patch. The name of the Kubernetes object to be scaled or patched 120 | type: string 121 | default: '' 122 | - name: replicas # Required when action is scale. The number of replicas desired 123 | type: number 124 | default: 1 125 | # Patch Kubernetes Deployments 126 | - name: mergeStrategy # Required when action is patch. The merge strategy to be used for applying the patch 127 | type: string 128 | default: strategic 129 | values: 130 | - strategic 131 | - merge 132 | - json 133 | - name: patch # Required when action is patch. The contents of the patch 134 | type: object 135 | default: '' 136 | # Delete Kubernetes Deployments 137 | - name: arguments # Required when action is delete. Args to be pass to kubectl for deleting the objects. e.g. arguments: 'deployment myApp' 138 | type: string 139 | default: '' 140 | 141 | steps: 142 | - template: ../preSteps.yaml 143 | parameters: 144 | clean: ${{ parameters.clean }} 145 | checkout: ${{ parameters.checkout }} 146 | submodules: ${{ parameters.submodules }} 147 | download: ${{ parameters.download }} 148 | artifact: ${{ parameters.artifactName }} 149 | preSteps: ${{ parameters.preSteps }} 150 | - ${{ if parameters.kubectlVersion }}: 151 | - task: KubectlInstaller@0 152 | inputs: 153 | kubectlVersion: '${{ parameters.kubectlVersion }}' 154 | - ${{ if parameters.keyVaultName }}: 155 | - task: AzureKeyVault@1 156 | displayName: 'Get Azure Key Vault ${{ parameters.keyVaultName }}' 157 | inputs: 158 | azureSubscription: '${{ parameters.keyVaultSubscription }}' 159 | KeyVaultName: '${{ parameters.keyVaultName }}' 160 | SecretsFilter: '${{ parameters.keyVaultSecretFilter }}' 161 | ${{ if gt(length(parameters.secretArguments), 1) }}: 162 | runAsPreJob: true 163 | - ${{ if parameters.secretArguments }}: 164 | - ${{ each secret in parameters.secretArguments }}: 165 | - task: KubernetesManifest@0 166 | displayName: 'Deploy secret ${{ secret.key }}' 167 | inputs: 168 | action: createSecret 169 | namespace: '${{ parameters.namespace }}' 170 | secretType: generic 171 | secretName: ${{ secret.key }} 172 | secretArguments: ${{ secret.value }} 173 | ${{ if parameters.kubernetesServiceConnection }}: 174 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 175 | - ${{ if and(parameters.replaceTokens, or(parameters.manifests, parameters.kustomizationPath, parameters.helmChart, parameters.dockerComposeFile)) }}: 176 | - task: replacetokens@3 177 | displayName: 'Replace tokens in Kube Manifests' 178 | inputs: 179 | rootDirectory: ${{ parameters.replaceTokensRoot }} 180 | targetFiles: ${{ parameters.manifests }} 181 | encoding: 'auto' 182 | writeBOM: true 183 | actionOnMissing: 'warn' 184 | keepToken: false 185 | tokenPrefix: '#{' 186 | tokenSuffix: '}#' 187 | useLegacyPattern: false 188 | enableTelemetry: false 189 | verbosity: 'detailed' 190 | - ${{ if and(parameters.kubernetesServiceConnection, parameters.dockerRegistryEndpoint, parameters.imagePullSecret) }}: 191 | - task: KubernetesManifest@0 192 | displayName: 'Create imagePullSecret ${{ parameters.imagePullSecret }} in ${{ parameters.namespace }} namespace' 193 | inputs: 194 | action: createSecret 195 | secretType: dockerRegistry 196 | secretName: '${{ parameters.imagePullSecret }}' 197 | dockerRegistryEndpoint: '${{ parameters.dockerRegistryEndpoint }}' 198 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 199 | namespace: '${{ parameters.namespace }}' 200 | - ${{ if or(parameters.kustomizationPath, parameters.helmChart, parameters.dockerComposeFile) }}: 201 | - task: KubernetesManifest@0 202 | name: bake 203 | displayName: 'Bake Manifests for Deployment' 204 | inputs: 205 | action: 'bake' 206 | ${{ if parameters.kustomizationPath }}: 207 | renderType: kustomize 208 | kustomizationPath: ${{ parameters.kustomizationPath }} 209 | ${{ if parameters.helmChart }}: 210 | renderType: helm2 211 | helmChart: ${{ parameters.helmChart }} 212 | overrideFiles: ${{ parameters.overrideFiles }} 213 | overrides: ${{ parameters.overrides }} 214 | releaseName: ${{ parameters.releaseName }} 215 | ${{ if parameters.dockerComposeFile }}: 216 | renderType: kompose 217 | dockerComposeFile: ${{ parameters.dockerComposeFile }} 218 | - ${{ if and(in(parameters.action, 'deploy', 'promote', 'reject'), or(parameters.manifests, parameters.kustomizationPath, parameters.helmChart, parameters.dockerComposeFile)) }}: 219 | - task: KubernetesManifest@0 220 | displayName: '${{ parameters.action }} to ${{ parameters.kubernetesServiceConnection }} ${{ parameters.namespace }} namespace' 221 | inputs: 222 | action: '${{ parameters.action }}' 223 | ${{ if parameters.kubernetesServiceConnection }}: 224 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 225 | namespace: '${{ parameters.namespace }}' 226 | ${{ if parameters.imagePullSecret }}: 227 | imagePullSecrets: '${{ parameters.imagePullSecret }}' 228 | ${{ if parameters.manifests }}: 229 | manifests: ${{ parameters.manifests }} 230 | ${{ if and(not(parameters.manifests), or(parameters.kustomizationPath, parameters.helmChart, parameters.dockerComposeFile)) }}: 231 | manifests: $(bake.manifestsBundle) 232 | rolloutStatusTimeout: '${{ parameters.rolloutStatusTimeout }}' 233 | ${{ if parameters.containers }}: 234 | containers: '${{ parameters.containers }}' 235 | ${{ if eq(parameters.strategy, 'canary') }}: 236 | strategy: canary 237 | percentage: '${{ parameters.percentage }}' 238 | trafficSplitMethod: '${{ parameters.trafficSplitMethod }}' 239 | ${{ if eq(parameters.trafficSplitMethod, 'smi') }}: 240 | baselineAndCanaryReplicas: '${{ parameters.baselineAndCanaryReplicas }}' 241 | - ${{ if and(eq(parameters.action, 'scale'), parameters.name) }}: 242 | - task: KubernetesManifest@0 243 | displayName: '${{ parameters.action }} ${{ parameters.name }} ${{ parameters.kind }} in ${{ parameters.namespace }} namespace' 244 | inputs: 245 | ${{ if parameters.kubernetesServiceConnection }}: 246 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 247 | action: '${{ parameters.action }}' 248 | namespace: '${{ parameters.namespace }}' 249 | kind: '${{ parameters.kind }}' 250 | name: '${{ parameters.name }}' 251 | replicas: ${{ parameters.replicas }} 252 | - ${{ if and(eq(parameters.action, 'patch'), parameters.name, parameters.patch) }}: 253 | - task: KubernetesManifest@0 254 | displayName: '${{ parameters.action }} ${{ parameters.name }} ${{ parameters.kind }} in ${{ parameters.namespace }} namespace' 255 | inputs: 256 | ${{ if parameters.kubernetesServiceConnection }}: 257 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 258 | action: '${{ parameters.action }}' 259 | namespace: '${{ parameters.namespace }}' 260 | kind: '${{ parameters.kind }}' 261 | name: '${{ parameters.name }}' 262 | mergeStrategy: ${{ parameters.mergeStrategy }} 263 | patch: ${{ parameters.patch }} 264 | - ${{ if and(eq(parameters.action, 'delete'), parameters.arguments) }}: 265 | - task: KubernetesManifest@0 266 | displayName: '${{ parameters.action }} ${{ parameters.arguments }} in ${{ parameters.namespace }} namespace' 267 | inputs: 268 | ${{ if parameters.kubernetesServiceConnection }}: 269 | kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}' 270 | action: '${{ parameters.action }}' 271 | namespace: '${{ parameters.namespace }}' 272 | arguments: '${{ parameters.arguments }}' 273 | - template: ../postSteps.yaml 274 | parameters: 275 | postSteps: ${{ parameters.postSteps }} 276 | clean: ${{ parameters.clean }} 277 | -------------------------------------------------------------------------------- /steps/deploy/terraformTemplate.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: downloadArtifact 19 | type: string 20 | default: '' 21 | - name: replaceTokens # Enable replace tokens task 22 | type: boolean 23 | default: false 24 | # postSteps 25 | - name: postSteps 26 | type: stepList 27 | default: [] 28 | - name: publishPlan # Publish artifact for $(jsonPlanFilePath) 29 | type: string 30 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)_OutputPlan' 31 | - name: publishVariables # Publish artifact for $(jsonOutputVariablesPath) 32 | type: string 33 | default: '$(Build.BuildNumber)_$(System.StageName)_$(Agent.JobName)_OutputVariables' 34 | - name: publishEnabled 35 | type: string 36 | default: true 37 | # Terraform Tasks 38 | - name: terraformVersion # The version of Terraform which should be installed on the agent if not already present 39 | type: string 40 | default: '' 41 | - name: provider # The name of the provider used in the terraform configuration files. Only one provider must be specified in the terraform configuration files in the below specified configuration directory. 42 | type: string 43 | default: azurerm 44 | values: 45 | - azurerm 46 | - aws 47 | - gcp 48 | - name: commands # The terraform command to execute in this order. Set value for command for commandOptions, - command: commandOptions | e.g. - apply: '-var "foo=bar"' 49 | type: object 50 | default: 51 | - init 52 | - plan 53 | - validate 54 | - apply 55 | - name: autoApprove # Skip interactive approval of plan before applying 56 | type: boolean 57 | default: true 58 | - name: workingDirectory # Directory containing the Terraform configuration files. 59 | type: string 60 | default: $(Build.Repository.LocalPath) 61 | # Backend 62 | - name: backendKey # The path to the Terraform remote state file inside the AzureRM storage container or AWS S3 Bucket. For GCP the backendkey is mapped to the gcpPrefix. The relative path to the state file inside the GCP bucket. 63 | type: string 64 | default: terraform.tfstate 65 | - name: serviceConnection # Required service connection name for provider 66 | type: string 67 | default: '' 68 | # Backend: Azure 69 | - name: resourceGroupName # Required for AzurRM provider, the name of the resource group which contains the storage account selected below. 70 | type: string 71 | default: '' 72 | - name: storageAccountName # Required for AzurRM provider, the name of the storage account which contains the Azure Blob container selected below. 73 | type: string 74 | default: '' 75 | - name: containerName # Required for AzurRM provider, the name of the Azure Blob container in which to store the Terraform remote state file. 76 | type: string 77 | default: '' 78 | # Backend: AWS or GCP 79 | - name: bucketName # Required for AWS or GCP provider, the name of the Amazon Simple Storage Service(S3) bucket or GCP storage bucket for storing the Terraform remote state file. 80 | type: string 81 | default: '' 82 | # Replace Tokens Task 83 | - name: replaceTokens # Enable replace tokens task 84 | type: boolean 85 | default: false 86 | - name: replaceTokensTargets 87 | type: string 88 | default: '**.tf*' 89 | 90 | steps: 91 | - template: ../preSteps.yaml 92 | parameters: 93 | clean: ${{ parameters.clean }} 94 | checkout: ${{ parameters.checkout }} 95 | submodules: ${{ parameters.submodules }} 96 | download: ${{ parameters.download }} 97 | artifact: ${{ parameters.downloadArtifact }} 98 | preSteps: ${{ parameters.preSteps }} 99 | - ${{ if parameters.replaceTokens }}: 100 | - task: replacetokens@3 101 | displayName: 'Replace Tokens in ${{ parameters.workingDirectory }}' 102 | inputs: 103 | rootDirectory: '${{ parameters.workingDirectory }}' 104 | targetFiles: '${{ parameters.replaceTokensTargets }}' 105 | - ${{ if parameters.terraformVersion }}: 106 | - task: TerraformInstaller@0 107 | displayName: 'Terraform Install ${{ parameters.terraformVersion }}' 108 | inputs: 109 | terraformVersion: ${{ parameters.terraformVersion }} 110 | - ${{ each command in parameters.commands }}: 111 | - ${{ if in(command.key, 'init', 'plan', 'validate', 'apply', 'destroy') }}: 112 | - task: TerraformTaskV1@0 113 | ${{ if not(command.displayName) }}: 114 | displayName: 'Terraform ${{ command.key }} ${{ command.value }}' 115 | ${{ if command.displayName }}: 116 | displayName: ${{ command.displayName }} 117 | ${{ if command.condition }}: 118 | condition: ${{ command.condition }} 119 | ${{ if command.continueOnError }}: 120 | continueOnError: ${{ command.continueOnError }} 121 | ${{ if command.timeoutInMinutes }}: 122 | timeoutInMinutes: ${{ command.timeoutInMinutes }} 123 | inputs: 124 | command: ${{ command.key }} 125 | # command: init 126 | ${{ if and(eq(command.key, 'init'), command.value) }}: 127 | commandOptions: '${{ command.value }}' 128 | # command: plan 129 | ${{ if eq(command.key, 'plan') }}: 130 | # If commands contains plan and destroy 131 | ${{ if and(contains(join('-', parameters.commands), 'destroy')) }}: 132 | # and if command has value, insert -destroy flag and additional commandOptions 133 | ${{ if command.value }}: 134 | commandOptions: '-destroy ${{ command.value }}' 135 | # and if no additional commandOptions, insert -destroy flag for commandOptions 136 | ${{ if not(command.value) }}: 137 | commandOptions: '-destroy' 138 | # If command is plan and commands does not contain destroy 139 | ${{ if not(contains(join('-', parameters.commands), 'destroy')) }}: 140 | commandOptions: '${{ command.value }}' 141 | # command: validate 142 | ${{ if and(eq(command.key, 'validate'), command.value) }}: 143 | commandOptions: '${{ command.value }}' 144 | # command: apply 145 | ${{ if eq(command.key, 'apply') }}: 146 | # If autoApprove is true insert -auto-approve flag 147 | ${{ if parameters.autoApprove }}: 148 | # If additional commandOptions insert -auto-approve and commandOptions 149 | ${{ if command.value }}: 150 | commandOptions: '-auto-approve ${{ command.value }}' 151 | ${{ if not(command.value) }}: 152 | commandOptions: '-auto-approve' 153 | # command: destroy 154 | ${{ if and(eq(command.key, 'destroy'), command.value) }}: 155 | commandOptions: '${{ command.value }}' 156 | provider: ${{ parameters.provider }} 157 | workingDirectory: ${{ parameters.workingDirectory }} 158 | ${{ if and(eq(parameters.provider, 'azurerm'), parameters.serviceConnection, parameters.resourceGroupName, parameters.storageAccountName, parameters.containerName) }}: 159 | backendServiceArm: ${{ parameters.serviceConnection }} 160 | backendAzureRmResourceGroupName: ${{ parameters.resourceGroupName }} 161 | backendAzureRmStorageAccountName: ${{ parameters.storageAccountName }} 162 | backendAzureRmContainerName: ${{ parameters.containerName }} 163 | backendAzureRmKey: ${{ parameters.backendKey }} 164 | ${{ and(eq(parameters.provider, 'aws'), parameters.serviceConnection, parameters.bucketName) }}: 165 | backendServiceAWS: ${{ parameters.serviceConnection }} 166 | backendAWSBucketName: ${{ parameters.bucketName }} 167 | backendAWSKey: ${{ parameters.backendKey }} 168 | ${{ and(eq(parameters.provider, 'gcp'), parameters.serviceConnection, parameters.bucketName) }}: 169 | backendServiceGCP: ${{ parameters.serviceConnection }} 170 | backendGCPBucketName: ${{ parameters.bucketName }} 171 | backendGCPPrefix: ${{ parameters.backendKey }} 172 | - ${{ if and(parameters.publishPlan, parameters.publishEnabled) }}: 173 | - publish: $(jsonPlanFilePath) 174 | artifact: ${{ if parameters.publishPlan }} 175 | condition: gt(length(variables['jsonPlanFilePath']), 0) 176 | - ${{ if and(parameters.publishVariables, parameters.publishEnabled) }}: 177 | - publish: $(jsonOutputVariablesPath) 178 | artifact: ${{ if parameters.publishVariables }} 179 | condition: gt(length(variables['jsonOutputVariablesPath']), 0) 180 | - template: ../postSteps.yaml 181 | parameters: 182 | postSteps: ${{ parameters.postSteps }} 183 | publish: false 184 | clean: ${{ parameters.clean }} 185 | -------------------------------------------------------------------------------- /steps/postSteps.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: postSteps # Insert stepList before publish and clean 3 | type: stepList 4 | default: [] 5 | - name: clean # Enable post build clean task 6 | type: boolean 7 | default: false 8 | - name: publish # path to a file or polder 9 | type: string 10 | default: '' 11 | - name: artifact # Name of artifact to publish 12 | type: string 13 | default: '' 14 | 15 | steps: 16 | - ${{ if gt(length(parameters.postSteps), 0) }}: 17 | - ${{ parameters.postSteps }} 18 | - ${{ if parameters.publish }}: 19 | - publish: ${{ parameters.publish }} 20 | displayName: Publish Pipeline Artifact ${{ parameters.artifact }} 21 | ${{ if parameters.artifact }}: 22 | artifact: ${{ parameters.artifact }} 23 | - ${{ if parameters.clean }}: 24 | - task: PostBuildCleanup@3 25 | displayName: Clean Agent Directories -------------------------------------------------------------------------------- /steps/preSteps.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: preSteps # Insert stepList after checkout and download 3 | type: stepList 4 | default: [] 5 | - name: checkout # self | none | repo name | false # self is the repo containing the pipeline yaml. When false step is not inserted, when none it's disabled 6 | type: string 7 | default: self 8 | - name: clean # if true, run execute git clean --ffdx && git reset -hard HEAD before fetching 9 | type: boolean 10 | default: false 11 | - name: submodules # true for single level of submodules or recursive to get submodules of submodules 12 | type: string 13 | default: false 14 | values: 15 | - true 16 | - false 17 | - recursive 18 | - name: download # current | pipeline resource identifier | none | false # When false step is not inserted, when none it's disabled 19 | type: string 20 | default: current 21 | - name: artifact # Optional param to specify an artifact name to download. Default downloads all artifacts for current pipeline run 22 | type: string 23 | default: '' 24 | - name: patterns # File matching patterns should assume the first segment of the pattern is (or matches) an artifact name. For example, WebApp/** matches all files from the WebApp artifact. The pattern */*.dll matches all files with a .dll extension at the root of each artifact. 25 | type: string 26 | default: '' 27 | 28 | steps: 29 | - ${{ if and(ne(parameters.checkout, 'false'), ne(parameters.checkout, '')) }}: 30 | - checkout: ${{ parameters.checkout }} 31 | clean: ${{ parameters.clean }} 32 | ${{ if or(eq(parameters.submodules, 'true'), eq(parameters.submodules, 'recursive')) }}: 33 | submodules: ${{ parameters.submodules }} 34 | - ${{ if ne(parameters.download, 'false') }}: 35 | - download: ${{ parameters.download }} 36 | displayName: 'Download Pipeline Artifact ${{ parameters.artifact }} ${{ parameters.patterns }}' 37 | ${{ if parameters.artifact }}: 38 | artifact: ${{ parameters.artifact }} 39 | ${{ if parameters.patterns }}: 40 | patterns: ${{ parameters.patterns }} 41 | - ${{ if gt(length(parameters.preSteps), 0) }}: 42 | - ${{ parameters.preSteps }} 43 | -------------------------------------------------------------------------------- /steps/test/visualStudioTest.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: clean 3 | type: boolean 4 | default: false 5 | # preSteps 6 | - name: preSteps 7 | type: stepList 8 | default: [] 9 | - name: checkout 10 | type: string 11 | default: self 12 | - name: submodules 13 | type: string 14 | default: false 15 | - name: download 16 | type: string 17 | default: current 18 | - name: artifactName # artifactName or projects required 19 | type: string 20 | default: '' 21 | # Replace Tokens in files 22 | - name: replaceTokens # Enable replace tokens task. Useful for updating configuration settings in files like appsettings 23 | type: boolean 24 | default: false 25 | - name: replaceTokensRoot 26 | type: string 27 | default: '$(Pipeline.Workspace)' 28 | - name: replaceTokensTargets 29 | type: object 30 | default: | 31 | **appsettings.*.json 32 | # Use dotNet Type and Version 33 | - name: dotNetType 34 | type: string 35 | default: sdk 36 | values: 37 | - sdk 38 | - runtime 39 | - name: dotNetVersion 40 | type: string 41 | default: '' 42 | # dotNet restore/build 43 | - name: dotNetProjects # projects required to dotNet build a project before vsTest tasks 44 | type: string 45 | default: '' 46 | - name: dotNetArguments 47 | type: string 48 | default: '' 49 | - name: dotNetFeedRestore 50 | type: string 51 | default: '' 52 | - name: dotNetConfiguration 53 | type: string 54 | default: Release 55 | # Get Azure KeyVault as Variables for Replace Tokens 56 | - name: keyVaultName 57 | type: string 58 | default: '' 59 | - name: keyVaultSubscription 60 | type: string 61 | default: '' 62 | - name: keyVaultSecretFilter 63 | type: string 64 | default: '*' 65 | # VSTest Platform Installer 66 | - name: packageFeedSelector 67 | type: string 68 | default: nugetOrg 69 | values: 70 | - nugetOrg 71 | - customFeed 72 | - name: versionSelector 73 | type: string 74 | default: latestStable 75 | values: 76 | - latestStable 77 | - latestPreRelease 78 | - specificVersion 79 | - name: testPlatformVersion # Required when versionSelector is specificVersion 80 | type: string 81 | default: '16.8.3' 82 | - name: vsTestVersion 83 | type: string 84 | default: toolsInstaller 85 | # VSTest Task Params 86 | - name: testPlan # test plan ID number. Select a test plan number containing test suites with automated test cases. 87 | type: number 88 | default: 0 89 | - name: testSuite # test suite ID within the test plan. Select one or more test suites containing automated test cases. Test case work items must be associated with an automated test method. 90 | type: number 91 | default: 0 92 | - name: testConfiguration # test configuration number required if using testPlan and testSuite. Select Test Configuration. 93 | type: number 94 | default: 523 95 | - name: testAssemblies # Run tests from the specified files. When not using testPlan or testSuite. The file paths are relative to the search folder. Supports multiple lines of minimatch patterns. 96 | type: object 97 | default: '' 98 | - name: testSearchFolder # Folder to search for the test assemblies. 99 | type: string 100 | default: $(Pipeline.Workspace) 101 | - name: testResultsFolder 102 | type: string 103 | default: $(Agent.TempDirectory)\TestResults 104 | - name: testRunTitle 105 | type: string 106 | default: 'Visual Studio Test' 107 | - name: testDiagnosticsEnabled 108 | type: boolean 109 | default: false 110 | - name: testCollectDumpOn 111 | type: string 112 | default: onAbortOnly 113 | values: 114 | - always 115 | - onAbortOnly 116 | - never 117 | - name: runInParallel 118 | type: boolean 119 | default: true 120 | - name: rerunMaxAttempts # Maximum number of times a failed test should be retried. When greater than 0 rerunFailedTests is true 121 | type: number 122 | default: 0 123 | - name: minimumExpectedTests # the minimum number of tests that should be run for the task to succeed. Total tests run is calculated as the sum of passed, failed and aborted tests. 124 | type: number 125 | default: 1 126 | - name: continueOnError # If vsTest has failure, continue on error 127 | type: boolean 128 | default: false 129 | - name: platform # Build platform against which the tests should be reported. If you have defined a variable for platform in your build task, use that here. 130 | type: string 131 | default: 'Any CPU' 132 | - name: distributionBatchType 133 | type: string 134 | default: basedOnTestCases 135 | values: 136 | - basedOnTestCases 137 | - basedOnExecutionTime 138 | - basedOnAssembly 139 | - name: customBatchSizeValue # Optional when distributionBatchType is basedOnTestCases. Set to value greater than 0 to enable custom batch sizing 140 | type: number 141 | default: 0 142 | - name: customRunTimePerBatchValue # Optional when distributionBatchType is BasedOnExecutionTime 143 | type: number 144 | default: 0 145 | - name: codeCoverageEnabled 146 | type: boolean 147 | default: false 148 | # postSteps 149 | - name: postSteps 150 | type: stepList 151 | default: [] 152 | - name: publishEnabled 153 | type: boolean 154 | default: true 155 | - name: publishArtifact 156 | type: string 157 | default: '$(Build.DefinitionName)_$(System.JobName)' 158 | 159 | steps: 160 | - template: ../preSteps.yaml 161 | parameters: 162 | clean: ${{ parameters.clean }} 163 | checkout: ${{ parameters.checkout }} 164 | submodules: ${{ parameters.submodules }} 165 | download: ${{ parameters.download }} 166 | ${{ if and(parameters.artifactName, not(parameters.projects)) }}: 167 | artifact: ${{ parameters.artifactName }} 168 | preSteps: ${{ parameters.preSteps }} 169 | - ${{ if or(parameters.projects, parameters.artifactName) }}: 170 | - template: ../build/dotNetCore.yaml 171 | parameters: 172 | clean: false 173 | checkout: false 174 | download: false 175 | command: build 176 | packageType: ${{ parameters.dotNetType }} 177 | version: ${{ parameters.dotNetVersion }} 178 | projects: ${{ parameters.dotNetProjects }} 179 | feedRestore: ${{ parameters.dotNetFeedRestore }} 180 | arguments: ${{ parameters.dotNetArguments }} 181 | configuration: ${{ parameters.dotNetConfiguration }} 182 | - ${{ if and(parameters.keyVaultName, parameters.keyVaultSubscription) }}: 183 | - task: AzureKeyVault@1 184 | displayName: 'Get Azure Key Vault ${{ parameters.keyVaultName }}' 185 | inputs: 186 | azureSubscription: '${{ parameters.keyVaultSubscription }}' 187 | KeyVaultName: '${{ parameters.keyVaultName }}' 188 | SecretsFilter: '${{ parameters.keyVaultSecretFilter }}' 189 | - ${{ if parameters.replaceTokens }}: 190 | - task: replacetokens@3 191 | displayName: 'Replace tokens in ${{ parameters.replaceTokensRoot }}' 192 | inputs: 193 | rootDirectory: '${{ parameters.replaceTokensRoot }}' 194 | targetFiles: ${{ parameters.replaceTokensTargets }} 195 | encoding: 'auto' 196 | writeBOM: true 197 | actionOnMissing: 'warn' 198 | keepToken: false 199 | tokenPrefix: '#{' 200 | tokenSuffix: '}#' 201 | useLegacyPattern: false 202 | enableTelemetry: false 203 | verbosity: 'detailed' 204 | - ${{ if eq(parameters.vsTestVersion, 'toolsInstaller') }}: 205 | - task: VisualStudioTestPlatformInstaller@1 206 | displayName: 'Visual Studio Test Platform Installer' 207 | inputs: 208 | packageFeedSelector: '${{ parameters.packageFeedSelector }}' 209 | versionSelector: '${{ parameters.versionSelector }}' 210 | ${{ if eq(parameters.versionSelector, 'specificVersion') }}: 211 | testPlatformVersion: '${{ parameters.testPlatformVersion }}' 212 | - task: VSTest@2 213 | displayName: '${{ parameters.displayName }}' 214 | continueOnError: ${{ parameters.continueOnError }} 215 | inputs: 216 | # Distribution batch type runs its tests at the same time and results are published for the batch 217 | distributionBatchType: '${{ parameters.distributionBatchType }}' 218 | # If distributionBatchType is BasedOnTestCases and customBatchSizeValue greater than 0 the batchingBasedOnAgentOptions is customBatchSize 219 | ${{ if and(eq(parameters.distributionBatchType, 'BasedOnTestCases'), gt(parameters.customBatchSizeValue, 0)) }}: 220 | batchingBasedOnAgentsOption: customBatchSize 221 | customBatchSizeValue: ${{ parameters.customBatchSizeValue }} 222 | # If customBatchSizeValue is default of 0 then use autoBatchSize 223 | ${{ if and(eq(parameters.distributionBatchType, 'BasedOnTestCases'), eq(parameters.customBatchSizeValue, 0)) }}: 224 | batchingBasedOnAgentsOption: autoBatchSize 225 | # If distributionBatchType is basedOnExecutionTime and customRunTimePerBatchValue greater than 0 the batchingBasedOnExecutionTimeOption is customTimeBatchSize 226 | ${{ if and(eq(parameters.distributionBatchType, 'basedOnExecutionTime'), gt(parameters.customRunTimePerBatchValue, 0)) }}: 227 | customRunTimePerBatchValue: ${{ parameters.customRunTimePerBatchValue }} 228 | batchingBasedOnExecutionTimeOption: customTimeBatchSize 229 | # If customTimeBatchSize is default of 0 then use autoBatchSize 230 | ${{ if and(eq(parameters.distributionBatchType, 'basedOnExecutionTime'), eq(parameters.customRunTimePerBatchValue, 0)) }}: 231 | batchingBasedOnExecutionTimeOption: autoBatchSize 232 | # If testPlan and testSuite has values testSelector is testPlan 233 | ${{ if and(parameters.testPlan, parameters.testSuite, not(parameters.testAssemblies)) }}: 234 | testSelector: testPlan 235 | testPlan: ${{ parameters.testPlan }} 236 | testSuite: ${{ parameters.testSuite }} 237 | testConfiguration: ${{ parameters.testConfiguration }} 238 | # If testAssemblies has values and not testPlan or testSuite, then testSelector is testAssemblies 239 | ${{ if and(parameters.testAssemblies, not(parameters.testPlan), not(parameters.testSuite)) }}: 240 | testSelector: testAssemblies 241 | testAssemblyVer2: ${{ parameters.testAssemblies }} 242 | testRunTitle: '${{ parameters.testRunTitle }}' 243 | collectDumpOn: '${{ parameters.testCollectDumpOn }}' 244 | searchFolder: '${{ parameters.testSearchFolder }}' 245 | resultsFolder: '${{ parameters.testResultsFolder }}' 246 | diagnosticsEnabled: ${{ parameters.testDiagnosticsEnabled }} 247 | runInParallel: ${{ parameters.runInParallel }} 248 | # If rerunMaxAttempts value greater than 0 then rerunFailedTests is true, else false 249 | ${{ if gt(parameters.rerunMaxAttempts, 0) }}: 250 | rerunFailedTests: true 251 | rerunMaxAttempts: ${{ parameters.rerunMaxAttempts }} 252 | ${{ if eq(parameters.rerunMaxAttempts, 0) }}: 253 | rerunFailedTests: false 254 | minimumExpectedTests: ${{ parameters.minimumExpectedTests }} 255 | codeCoverageEnabled: ${{ parameters.codeCoverageEnabled }} 256 | vsTestVersion: '${{ parameters.vsTestVersion }}' 257 | platform: '${{ parameters.platform }}' 258 | configuration: '${{ parameters.configuration }}' 259 | - template: ../postSteps.yaml 260 | parameters: 261 | postSteps: ${{ parameters.postSteps }} 262 | ${{ if parameters.publishEnabled }}: 263 | publish: '${{ parameters.testResultsFolder }}' 264 | artifact: ${{ parameters.publishArtifact }} 265 | clean: ${{ parameters.clean }} 266 | --------------------------------------------------------------------------------