Azure Pipelines - VishalPatangay/My-devops-repo GitHub Wiki
Key concepts overview
What are Azure Pipelines tasks? In Azure Pipelines, a task is a packaged script or procedure that's been abstracted with a set of inputs.
Here's an example that uses the DotNetCoreCLI@2 task to build a C# project that targets .NET Core:
task: DotNetCoreCLI@2 displayName: 'Build the project' inputs: command: 'build' arguments: '--no-restore --configuration Release' projects: '**/*.csproj'
Let's break this task down a bit more:
The DotNetCoreCLI@2 task maps to the dotnet command. displayName defines the task name that's shown in the user interface. You'll see this in action soon. inputs defines arguments that are passed to the command. command specifies to run the dotnet build subcommand. arguments specifies additional arguments to pass to the command. projects specifies which projects to build. This example uses the wildcard pattern **/*.csproj. Both ** and *.csproj are examples of what are called glob patterns. The ** part specifies to search the current directory and all child directories. The *.csproj part specifies any .csproj file. Wildcards let you act on multiple files without specifying each one. If you need to act on a specific file only, you can specify that file instead of using wildcards.
"@" in the command refers to the version of the task.
https://docs.microsoft.com/en-gb/learn/modules/create-a-build-pipeline/4-plan-build-tasks
How are tasks used in a pipeline?
To add tasks to a pipeline you can drag and drop each task and configure as per your requirement. or A YAML file. YAML is a compact format that makes it easy to structure the kind of data that's in configuration files. You typically maintain this YAML file directly with your application's source code. Visual Studio code can be used to build a YAML file.
Below is the list of all the tasks using different tools listed: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/?view=azure-devops
key concepts graphic
A trigger tells a Pipeline to run. This could be a push to a repository. A pipeline is made up of one or more stages. A pipeline can deploy to one or more environments. A stage is a way of organizing jobs in a pipeline and each stage can have one or more jobs. Each job runs on one agent. A job can also be agentless. Each agent runs a job that contains one or more steps. A step can be a task or script and is the smallest building block of a pipeline. A task is a pre-packaged script that performs an action, such as invoking a REST API or publishing a build artifact. An artifact is a collection of files or packages published by a run..
Task Types: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml A task is a building block for defining automation in a pipeline. A task is simply a packaged script or procedure that has been abstracted with a set of inputs.
In YAML pipelines, you refer to tasks by name. If a name matches both an in-box task and a custom task, the in-box task will take precedence. You can use a fully-qualified name for the custom task to avoid this risk:
YAML
Steps:
- task: myPublisherId.myExtensionId.myContributionId.myTaskName@1 In Yaml when you use '@' it is used to represent a major version. And a number next to it tells which version is getting released.
Task Control Options: We can control the steps in the task by adding 'Keys' in the task section. example(https://docs.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#task-control-options)
- task: string # reference to a task and version, e.g. "VSBuild@1" condition: expression # see below continueOnError: boolean # 'true' if future steps should run even if this step fails; defaults to 'false' enabled: boolean # whether or not to run this step; defaults to 'true' timeoutInMinutes: number # how long to wait before timing out the task target: string # 'host' or the name of a container resource to target
Types of Jobs and syntax in Yaml: https://docs.microsoft.com/en-us/azure/devops/pipelines/process/phases?view=azure-devops&tabs=yaml
Script command Azure Pipelines task
npm install Npm@1
node-sass CmdLine@2
gulp gulp@1
echo date
CmdLine@2
dotnet restore DotNetCoreCLI@2
dotnet build DotNetCoreCLI@2
dotnet publish DotNetCoreCLI@2
There's no built-in task type that runs node-sass or prints the date to a file. For those, Mara uses the CmdLine@2 task, which lets her run any command that she wants.
A build task can compile source code, run unit tests, deploy an application to a staging environment, and more.
Exercise - Create the pipeline
When you create a pipeline, the process prompts you for your YAML file. The project doesn't have this file yet. Based on the selections and project type below Yaml file is created for you.
In Azure DevOps, go to your project.
Select Pipelines, either from the project page or from the left pane.
Select Create Pipeline.
On the Connect tab, select GitHub.
When prompted, enter your GitHub credentials.
On the Select tab, select your mslearn-tailspin-spacegame-web repository.
You might be redirected to GitHub to install the Azure Pipelines app. If so, scroll to the bottom and select Approve and install. On the Review tab, select Save and run. Then select Save and run a second time to commit your changes to GitHub and start the build.
Once you have a pipeline, you can add tasks to this pipeline https://docs.microsoft.com/en-gb/learn/modules/create-a-build-pipeline/6-create-the-pipeline
Remember that you're working from the master branch. You'll now create a branch named build-pipeline to hold your work. The branch gives you a place to experiment and get your build working completely without affecting the rest of the team.
You can add build tasks to azure-pipelines.yml directly from Azure Pipelines. Azure Pipelines will commit your changes directly to your branch. But here you'll modify azure-pipelines.yml locally and push, or upload, your changes to GitHub. Doing it this way lets you practice your Git skills. Watch the pipeline automatically build the application when you push up changes. In practice, you might add build tasks one at a time, push up your changes, and watch the build run. Here, you'll add all the build tasks we identified earlier at one time.
- git pull origin master - get the latest code from github, this checkout includes your yaml file.
- git checkout -b build-pipeline - to create a new branch named build-pipeline.
Azure Pipelines provides built-in build tasks that map to many common build activities. For example, the DotNetCoreCLI@2 task maps to the dotnet command-line utility. The pipeline uses DotNetCoreCLI@2 two times: one time to restore, or install, the project's dependencies and one time to build the project. Remember that not all build activities map to a built-in task. For example, there's no built-in task that runs the node-sass utility or writes build info to a text file.
git add azure-pipelines.yml git commit -m "Add build tasks" git push origin build-pipeline
Pushing the branch to GitHub triggers the build process in Azure Pipelines.
Publish the result to the pipeline
But where do the results of the build go? Right now, the output of the build remains on the temporary build server. You can store build artifacts in Microsoft Azure Pipelines so they're later available to others on your team after the build completes. That's what you'll do here. As a bonus, you'll also refactor the build configuration to use variables to make the configuration easier to read and keep up to date.
Note: Azure Pipelines enables you to automatically deploy the built application to a testing or production environment running in the cloud or in your datacenter. we are not doing this here though.
Publish the build to a pipeline
In .NET Core, you can package your application as a .zip file. You can then use the built-in PublishBuildArtifacts@1 task to publish the .zip file to Azure Pipelines.
trigger:
- '*'
pool: vmImage: 'ubuntu-18.04' demands: - npm
variables: buildConfiguration: 'Release' wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot' dotnetSdkVersion: '3.1.300'
steps:
-
task: UseDotNet@2 displayName: 'Use .NET Core SDK $(dotnetSdkVersion)' inputs: version: '$(dotnetSdkVersion)'
-
task: Npm@1 displayName: 'Run npm install' inputs: verbose: false
-
script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)' displayName: 'Compile Sass assets'
-
task: gulp@1 displayName: 'Run gulp tasks'
-
script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt' displayName: 'Write build info' workingDirectory: $(wwwrootDir)
-
task: DotNetCoreCLI@2 displayName: 'Restore project dependencies' inputs: command: 'restore' projects: '**/*.csproj'
-
task: DotNetCoreCLI@2 displayName: 'Build the project - $(buildConfiguration)' inputs: command: 'build' arguments: '--no-restore --configuration $(buildConfiguration)' projects: '**/*.csproj'
-
task: DotNetCoreCLI@2 displayName: 'Publish the project - $(buildConfiguration)' inputs: command: 'publish' projects: '**/*.csproj' publishWebProjects: false arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)' zipAfterPublish: true
-
task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' condition: succeeded()
The first task uses the DotNetCoreCLI@2 task to publish, or package, the application's build results (including its dependencies) into a folder. The zipAfterPublish argument specifies to add the built results to a .zip file.
The second task uses the PublishBuildArtifacts@1 task to publish the .zip file to Azure Pipelines. The condition argument specifies to run the task only when the previous task succeeds. succeeded() is the default condition, so you don't need to specify it. But we show it here to illustrate its use. git add azure-pipelines.yml git commit -m "Add publish tasks" git push origin build-pipeline
As you did earlier, from Azure Pipelines, trace the build through each of the steps.
When the pipeline completes, go back to the summary for the build.
Under Related there is 1 published. Select the artifact.
Expand the drop folder.
You see a .zip file that contains your built application and its dependencies:
Build multiple configurations by using templates
you implemented a pipeline that builds the Space Game web site. You started with a script that performs each build action and mapped each action to its corresponding pipeline task. The output of the pipeline is a .zip file that contains the compiled web application.
In this exercise, you use a template to define build tasks that can build any configuration defined in the project file. Templates enable you to define your logic one time and then reuse it several times. Templates combine the content of multiple YAML files into a single pipeline.
If you want to add say debug configuration to the existing yaml file, you may need to add the same set of tasks and replace build with debug, it will work but as the releases get complex this may not be the right approach.
-
task: DotNetCoreCLI@2 displayName: 'Build the project - Release' inputs: command: 'build' arguments: '--no-restore --configuration Release' projects: '**/*.csproj'
-
task: DotNetCoreCLI@2 displayName: 'Publish the project - Release' inputs: command: 'publish' projects: '**/*.csproj' publishWebProjects: false arguments: '--no-build --configuration Release --output $(Build.ArtifactStagingDirectory)/Release' zipAfterPublish: true
Better solution is to use a template
A template enables you to define common build tasks one time and reuse those tasks multiple times. You call a template from the parent pipeline as a build step. You can pass parameters into a template from the parent pipeline.
- mkdir templates directory at the root of your profile through visual studio code.
- In Visual Studio Code, select File > New File. Then select File > Save to save the blank file as build.yml in your project's templates directory. (For example, ~/mslearn-tailspin-spacegame-web/templates.)
- Add this code to buld.yml parameters: buildConfiguration: 'Release'
steps:
-
task: DotNetCoreCLI@2 displayName: 'Build the project - ${{ parameters.buildConfiguration }}' inputs: command: 'build' arguments: '--no-restore --configuration ${{ parameters.buildConfiguration }}' projects: '**/*.csproj'
-
task: DotNetCoreCLI@2 displayName: 'Publish the project - ${{ parameters.buildConfiguration }}' inputs: command: 'publish' projects: '**/*.csproj' publishWebProjects: false arguments: '--no-build --configuration ${{ parameters.buildConfiguration }} --output $(Build.ArtifactStagingDirectory)/${{ parameters.buildConfiguration }}' zipAfterPublish: true These tasks look like the ones you defined earlier to build and publish the application. But in a template you work with input parameters differently than you work with normal variables. Here are two differences:
In a template file, you use the parameters section instead of variables to define inputs. In a template file, you use ${{ }} syntax instead of $() to read a parameter's value. When you read a parameter's value, you include the parameters section in its name. For example, ${{ parameters.buildConfiguration }}.
Now, modify your azure pipelines file as below:
trigger:
- '*'
pool: vmImage: 'ubuntu-18.04' demands: - npm
variables: buildConfiguration: 'Release' wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot' dotnetSdkVersion: '3.1.300'
steps:
-
task: UseDotNet@2 displayName: 'Use .NET Core SDK $(dotnetSdkVersion)' inputs: version: '$(dotnetSdkVersion)'
-
task: Npm@1 displayName: 'Run npm install' inputs: verbose: false
-
script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)' displayName: 'Compile Sass assets'
-
task: gulp@1 displayName: 'Run gulp tasks'
-
script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt' displayName: 'Write build info' workingDirectory: $(wwwrootDir)
-
task: DotNetCoreCLI@2 displayName: 'Restore project dependencies' inputs: command: 'restore' projects: '**/*.csproj'
- template: templates/build.yml parameters: buildConfiguration: 'Debug'
- template: templates/build.yml parameters: buildConfiguration: 'Release'
- task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' condition: succeeded()
Now, run the below steps git add azure-pipelines.yml templates/build.yml git commit -m "Support build configurations" git push origin build-pipeline From Azure Pipelines, trace the build through each of the steps, as you did earlier.
As the pipeline runs, you see that the process expands the tasks within the template. The tasks that build and publish the project are run two times, once for each build configuration:
The expanded template tasks in Azure Pipelines
under Artifacts you see now You see that the pipeline produces a .zip file for both the Debug configuration and the Release configuration.
Merge branch into Master
In practice, you'd submit a pull request that merges your build-pipeline branch into the master branch.
Summary, more about YAML and CD https://docs.microsoft.com/en-gb/learn/modules/create-a-build-pipeline/10-summary