A closer look into VSTS Build and Release Management
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Osnabrugge, Rene van
With the release of TFS 2015 the new Build system was introduced. The changes compared to the old XAML build system are spectacular. It is now cross-platform, fast, light weight and task based. The same concepts apply to the new Release Management tooling that is available in Visual Studio Team Services and that will eventually flow in to the on-premise product. In this session we take a close look into the new build ad release system and talk about how you can benefit from them in your daily workflow. Even if you are not a Microsoft Developer!
 Welcome. I understand fully that it was a party last night. So thank you for being here so early at nine o'clock. There is not much people. I think that most of them are still in bed sleeping. So let me start with a short introduction. I have two laptops here. And that's why I came here this morning at eight o'clock. Started down my laptop. And now it says this. Updating Windows. So all the demo preparations that I did. Nice presentation. Nice Spotify playlist. Nice demos. It's going to be a little bit different now, I think. So I have the laptop of my colleague. My other laptop is at 88%. So I have good hopes that during this session it will come up again. I have some demos that I can only do on this one because I prepared it here. But most of the stuff that I'm going to show you is in the cloud. It's on Visual Studio Team Services. That's a cloud service. And it's on Azure. It is also a cloud service. So I think I can manage a whole lot to show you today. So that's what I'm going to do. This PowerPoint online, that's my only slide. So I will close this down. And then I will just start because I thought it was nice to have a demo-only session. So first I want to introduce myself. My name is Sriné van Osnabrige. I'm a lead consultant at XperiaT in the Netherlands. We are a firm that consults in ALM, in Azure, in Cloud and mobile. And I help companies in proving their software processes. So I really look broadly to people, as in tools. And my expertise is Visual Studio Team Services and Team Foundation Server. I'm an ALM MVP as well. And this photo was taken at Build. So I also have the HoloLens part in my session. There is also that HoloLens session next to me. So all the other people that are not in bed are probably there. So this was a great experience that I had there. And I can really recommend everybody to just, if you have the chance, just try it out because it's really, really awesome. Then in private I have a wife and two kids. My oldest is five and my youngest is two. Yesterday, two days ago, he was two. And that's it. I like to run sometimes. So without further ado, I want to just start with the demos. And then let me start my timer. Otherwise, I will just hopelessly run out of time. So first question, who works with VSTS already? Okay. Okay. And who works with the build and release management system already? Oh, okay. And then I hope that I can tell you some new stuff. So this is the intro page. So this is the dashboard. You can create all kinds of widgets and you can create your own stuff and you can put everything on there. So it's more a dashboard for entry point of VSTS. And there is also the work hub where we did what, which we can use to do some work on the management. So to walk you through what I'm, what we are going to do today, I created a small backlog. I already did the preparation, but not properly because my laptop crashed and was updating. I already did the introduction and I'm going to do the agenda. So what I'm going to do today, I'm not going to show you all the build steps that are in the box. I'm not going to do, okay, this build step can do that and this build step can do that. I want to really dive into what is build and release management, what are the conceptual things behind it? How do the agents work? How does the infrastructure work? How does the cross-platform build agents work, which only run on that machine? So I can show you the stuff that is really below the surface because all the tasks, it's really situational and it depends on the situation that you're in, what and how you are going to use it. So that's what we are going to do. First, then we are going to set up a build. We'll talk a little bit about, sorry, I will talk a little bit about setting up tests, updating, et cetera, et cetera, capabilities and demands, triggers, et cetera. Then we walk into VSTS release management, which you can see it's quite similar as the build system. Only you have the approval and validation parts in there as well. And then lastly, if my laptop works again, we can do some customization and extensions and I can show you how that works and I will show you a co-extension. Before I continue, my laptop is responding again. I can log in. So if everything works here, I can just start. So I can start with a simple demo here and then I can maybe move over. So first of all, I move to the build tab. This is where everything happens. So as you know or might not know, Microsoft had first exam build engine. Who used the exam build engine? Who liked it? So I think that the main reason why people use Jenkins and TeamCity was because of the exam build engine. It really was bad. It was, you could do stuff, but if you wanted to do something a little bit different than what was out of the box provided, you came into customization and that was really, really hard. You had to build assemblies and you had to put them in source control and you had to configure your controllers and it was really, really hard to do. So Microsoft understood that and they said, okay, we are going to build a new build engine. We are going to build an engine that is easily customizable, that can easily be extended and that is very, very lightweight to run. And that's what they did. And I think, and I use Jenkins at my assignment right now and I think it's better. I think it's really, really good. It's really fast and it's really handy in use. So let me just start with a simple build definition. When I press create new build definition, I can select templates. And what is a template? It's just a blueprint of something that I already did or what is provided out of the box by Microsoft. And as you can see here, it's not only a Microsoft based templates. You can see Android. You can see and, you can see Gradle. You can see Maven. So it's not only Microsoft related stuff that you can do. You can also do non-Microsoft related stuff. This is really great. So you have also deployment templates, which is nothing more than a build template with some build steps in there that can do deployment stuff. And I can have custom templates. So you can create your own template. For example, for your own components that has certain steps that you always want to follow or certain build numbers that has a certain format. And you can just save those templates and you can just create them from here. And then I can just say next. And then I will have this template as a base. Then I can select a repository. The repository is not only VSTS. You can select a VSTS repository and then I can select both. I can select a TFVC, so Team Foundation Virtual Control repository that resides in the same project or I can select a Git repository. What else I can do is I can move to GitHub. I can create a service endpoint to GitHub and I can extract my sources directly from GitHub and use the build engine of Microsoft in VSTS to just build my sources from GitHub directly. There is also the remote Git repository, which is just somewhere and subversion. Who uses subversion? So I don't know why it's there. I think that just good. So I select a repository. I select the default branch that I'm building and I can select the agent which I'm running on. So I come back to agents a little bit later, but this is now the hosted agent. So Microsoft has a pool of agents somewhere in the cloud that you can just use. So if you don't have fancy stuff to do and you don't want to set up infrastructure, you can just point to it, to the hosted pool and Microsoft provides the agents for you. So I can create. And then first thing I need to do is I can create a build step. A build step is a simple lightweight zip file. You should see it as a zip file which creates which has a manifest which describes the task. So you can see the name and the title and the input parameters and stuff. And it contains a PowerShell script or Node.js script, which is executed when you execute the build step. Microsoft is moving to Node and to.NET Core because that's cross platform. If you use PowerShell, it can only run on Windows based machines, of course. And if you use Node or you use.NET Core, you can use the same build tasks on multiple platforms. So Microsoft is really moving all their tasks to the new infrastructure. But most of them now are still in PowerShell and you can see the variants there. So let me just start by adding a simple PowerShell. And I can hit close. So I add a PowerShell script. I can choose whether I want to use inline or file path. And then I can just write some PowerShell script. So let me just be simple and easy. And I can just say hello, NDC. Save the template. I can give it the name. So let me just say first look build, for example. Okay. And then I just queue the build. So really simple. If I can, if I selected the template with contain more steps, it was somewhat more configuration. But I can just now hit enter. And now it will just start up my build. It will look in the hosted pool for an available agent. And what you see sometimes is if it's a little bit more busy, it takes a few seconds to just get an agent that is available to run my build. And then it's running. So what you see here is hello, NDC. So that's the output of my PowerShell script. Nothing fancy here. So let's dive a little bit further. For example, if I add another build step. And a PowerShell script. Make it inline again. And I just say, for example, I want to do a curl statement. So I want to do curl, HTTP, Google.com. And I will save this. If I queue the build now, it will, of course, run my first PowerShell script again. But what we'll see is that it will probably not run on the hosted agent. It will crash. And this is what I mean by it takes a while sometimes to connect to the hosted agent. So you will see it crashes. Why? Because on the hosted agent, curl is not installed. So the hosted agent does not contain everything you want. It contains the basic stuff. It contains the.NET frameworks and everything that you can expect from a Windows agent or a Linux agent. But it doesn't contain the tools that you need sometimes. So you can do two things. You can either provide the tools that you need by putting the XE files that you need to run curl, for example, and just copy it to the agent. And then execute that XE to do your thing on the hosted agent. Or you can run a on-premise agent. And that's what we are going to do. And my laptop works. So I'm going to switch machines. And then I'm going to come to show you on this laptop. So give me a sec. Okay. So I opened up the build that we just created. And what I want to do now, I want to switch to my on-premise agent. So for that, I'm going to the general tab. And I go to the default agent queue. And I press manage. Okay. I need to maybe connect. Yeah. So here we are. So in my management, I have queues. I have a default queue. I have multiple queues. And I have this hosted queue. So the hosted agent is always online. If this one is red, something is wrong at Microsoft. So we cannot do anything about it. This is always green. So we have the default pool. And we can create all kinds of agents in here. So what do we do? We can download an agent. If I press this one, and I won't do it for the time that I lost, it will download a zip file for me. And that zip file contains some files. You unblock the file. Very, very important to unblock the file. And then you extract the file to your local disk. So when I go to my command line, I have a NDC agent. So this is what it kind of looks like. So you have the agent directory in configure and run. That is what you initially get when you extract the file. Then you are going to configure the agent. So what that does, it wants to know to which collection am I connecting. How is this agent called, et cetera, et cetera. So it will now hopefully start connecting. Maybe I should switch back to the other machine. I'll show you. Okay, let's try something different. I will just try to download the agent again. So I will download the agent. I think the network connection is a little bit slow. This is the agent that I downloaded. So I will just copy this one. Create a new folder, NDCA. Extract it here. And let's try to do this one. I don't know why this is not working. Ah, okay. So I have to configure the agent. So I can say the name of the agent, the name of my server that I'm connecting to,.com, the pool to which I'm connecting. So you can create pools of agents, and you can share those pools amongst different collections that you have. In VSTS, you only have one collection, and one collection can have a pool, and you can attach a queue to a pool. If you have multiple collections, you can create another queue on another collection and connect it to the same pool. So that's how you can share your built infrastructure in your organization. If you used the XAML builds before, you had a build controller and a build controller ran on a machine, and it connected to one single collection. If you had another collection that you also wanted to use for your builds, you had to create a new machine with a new build controller. So it was not really scalable to use your build infrastructure. So instead, we can now share built queues. So I'm connecting to a build queue. Where do I want to get my sources? And I can say, where do you want to run this service as a Windows service, or do you just want to keep running in your console? What I usually do is I don't use the hosted agent much. Most of the time, just run in my console on my local machine. So when I'm doing building builds, creating builds, I just run a console and testing the builds because then it gets all the sources that I'm doing on my local machine, and I can easily debug. I can easily do stuff on the sources that it gets. I know what happens exactly because it's on my machine. And once it's running, I just will run on the build agent somewhere in our build infrastructure. So that's a really convenient way to just easily start up a new build agent or multiple build agents at the same time. So now I will just connect to my thing here. So I will sign into my account. So this build agent without firewall stuff, it connects to the default ports. It will connect to my VSTS account, and it will just start running. So here it's running, and in my... I had to start up somewhere here as well. That's all the preparations that I missed. So here you can see that I have the RVO Dell 2. Just the agent that I just started up, it's now running on this machine as well. I will just... Can I just remove this one? No. So when I go back to this build, and if you still remember because of all the do, we did a curl statement on this build. When I queue this build, I can say I want to run on the default queue. So not on the queue in the cloud, but on the default queue, and I can run. VSTS starts the build. It puts it in a queue. The queue finds an available agent, and then it starts to run the build. And you can see that it finds the RVO Dell 2 agent because that's now the only agent that is available because the other agent on that machine that I used before, I disabled that. Now I finally find one agent, so it will run there. So it will get sources, and then it will execute the PowerShell script twice, hopefully. Okay. Not recognized. So probably I did something wrong in the... OK, OK. Thanks. Yeah. So, but when I do this, it will run and it will show me the output of the crawl statement. That's not very interesting. But what is interesting is, so let me change this back so that it is default on the default queue and let me then quickly change this as well for the next run. What is interesting is that, obviously, when I run a build, sometimes it happens that my agents are not capable of running that build because they don't have the tools that I need to run that build. So how can I manage that? How can I make that controllable? We can do that by adding demands. So on this general tab, I also have demands. This demand means that I can say, I want to be something present on the build server when I run this specific build definition. I can say, for example, I want curl to be present. Curl must exist on this build agent. I can save. This is a manual step, so I can add anything that I want. So if I can sort of like tag my agents and tag my builds, so this build is a update to build and this build is a legacy build. So I can do all the demands. But there are also tasks that you can add. For example, there is a task gradle that I can add. And this gradle task, it automatically adds to the month Java. So if, oh, okay, sorry, if I want to run a gradle, it demands that Java is installed on the machine that I'm running on. So the task is configured to add that demand automatically. So let me just quickly remove that. When I run the build now, it tells me there is no agent that is capable of running this build. It demands curl, but there is no agent with curl. So sorry, you can queue it and wait forever or you can just fix it. So what we are going to do, of course, is trying to fix that. If I move to my agent that I just created, there is a tab, capabilities. So demands and capabilities, they are a pair. I demand something and my agent should have that capability to be able to run that. So what you can see here is that there are system capabilities. So Chef, DNX, Java, that's all system environment variables on my system. These are the tools that I have installed on my systems and it just reads the environment variables and it knows that Java is installed. If I need something extra, I can just say curl. And for example, one or true, I don't care because I just checked that curl exists. So if I save the changes here and I run this build again, then it will automatically queue and it will find an agent and it will only run on agents that have that curl capability configured on true. So it will now hopefully run and even run without errors because I just fixed it. So here is the curl output. So this is all the queue and the pool and how can you manage your build agents with demands and capabilities. So this is how you can steer your builds in your build infrastructure. This is not cross-platform yet. So what I want to show you now is I want to do the same thing for the build but run on a Linux-based agent. So when we create a new build definition and I will just do an empty build definition again, I will just select my NDC project, create, and I add a build step. But I'm not adding a PowerShell script but I'm adding a shell plus plus script. So this is the Linux-based thing to run PowerShell, for example, or command line. So I can just say echo as well NDC and if we look at the demands, it demands SH. It demands shell to be present on the agent that I'm running on. So if I press save now and I would just say Linux, save and I queued this build, I don't have an agent. I don't have a Linux agent running yet. So we are going to fix that. So I have a Linux machine running in the cloud and I need to quickly look up my password here. So this is a Linux machine. And what I can do is I can, of course, download the agent on this Linux machine, which I did. So there is a build agent here. But on Linux, we can do other stuff as well. We can also say we are going to run Docker because Docker is a very, very lightweight virtual machine-like thing. Who knows Docker, the concepts? Yeah? Okay. So instead of installing the agent on the machine, because the machine has all the environment variables, I have a specific version of Java and I have a specific version of whatever, node. Then I can only have agents that run on that specific version of software. While when I create virtual machines, I can have many virtual machines with agents installed and run different versions of software on that. So I can sometimes run with Java 7 and sometimes run with Java 8 or whatever. But if I do it in Docker, it's all the benefits of the virtual machine, but still smaller and very easy to roll out. So what I did is I created a Docker image that's called xperia.vsts build agent that has node installed. It's just a Docker container with a build agent configured and installed already, but it's not running yet. So if I'm going to run this container by saying, Docker run, minty i xperia slash fsts build agent bash, it will start up the container and you can see how quickly it is because it's already done. And then I can see the agent directory here. So I will go into there. And then I will come, I can say, switch user because I cannot run this service sa root user. That's not allowed on Linux. So I have to switch to another user. And then I can just say, run. It asks me for my username to connect. I already configured this agent to look at my collection. I run and you can see it's just easy starting up this container. And I can also do it by Docker run that it automatically starts up the agent already because then you don't have to configure it manually, but this just for demo purposes. So when I look now, I have a Docker agent running as well. So when I queue this build now, it will go to the same queue and finds me an agent that has SH installed. And that is, in this case, my Docker agent. And then it will just automatically pop up my NDC message here as well. So you can imagine, and I won't show you now because I want to save a little bit time, that if I just exit this container and say, okay, I now want to run another container with a Java version 8 installed and I'm doing a Java build which demands me a Java installation. I can just easily start up a new container. For example, the VSTS build agent Java, it automatically pops up and the whole infrastructure makes sure that it will run on the container that is capable of running that specific build. So I did two blog posts on build agents in Docker containers, both on Linux and Windows because Windows is also now capable of running Docker containers in a preview mode. So you can look at road2alm.com and there are two blog posts there that describe how to do this. It's really convenient way to just quickly start up new agents and do some configuration there. So that's really great. So leaving my Linux build for what it is because after all, I'm still a Windows guy. Let us walk to the rest of this build possibilities. So I opened up the wrong one. So let me open up this one. So let me walk you through a template. So if I choose the template Visual Studio build, it will provide me this template. So it will do some Nuke at restore. It will do a Visual Studio build. It will run some unit tests that it can find. It will publish symbols. And then I added two tasks, copy files, which is more or less create a nice structure for your build drops. So you can publish artifacts to your build. But if you do nothing, it will just publish everything that's in the binary directories and you have everything. But if you want to have nice folders, for example, I want to folder with my website and I want to have a folder with my tests and I want to have a folder with my other components, you can use the copy files tasks to just copy everything to a sub directory. And then at the end, you can just publish the whole lot as a build artifact to the build. So that's what I did. If I am going to look at the solution, then what you will see is that we have values in the MS build arguments. And for me, this is was that there was something to get used to. But because normally when you use the XAML builds, you just said, OK, I want to build this solution. And then you had some checkboxes like I want to do code analysis. And I want to do I want to create an MS deploy file. And it was just checkboxes and then you could run and then you had it. The new build agent, it is very lightweight and it does not really things for you. There are steps that can be created that does the stuff. But it's doing nothing automatically. So if we want to do visual studio build, and in my case, I'm building a website and I want to provide, I want to, I want to copy a zip file. I want to create an MS deploy zip file that contains my website. I have to do some MS build magic. So you have to know MS build a little bit more than you maybe did before when using the other stuff. You have to know what's happening inside MS build, what MS build needs to be able to do the stuff. So in this case, I want to do a web deployment. So I have to add the parameters deploy on build, web publish method, package as a single file. And I also have this one run code analysis. First it was just a checkbox run the code analysis and then underwater it's called MS build with this parameter. If you don't now want to run code analysis, you just have to specify this parameter and then it will run it automatically for you. And then you have the package location and this one is maybe a special value. This is the build.staging directory. So the dollar bracket open value. What's that? That's a variable that you can use within the build pipeline. So let us move to the variables tab. If I look at the variables, first start with the predefined variables. There are lots of them that you can just use in your build pipeline. So for example, the build directory, the home directory, what's the name of the agent that I'm running on? What's the name of the, what's the path of my artifact location? What's the path of my source location? What's the path of my binary location, et cetera, et cetera. All those variables are present and you can reference those variables in all the steps by just putting dollar sign, bracket open, name of the variable, bracket close. When running PowerShell, it just injects them as environment variables and you can refer to them by column and then the name of the variable. So that's really useful. You have all those variables always at your servers. So you can also, of course, create your own variables. So just add a new one, give it a name and give it a value. For example, password. Let me do that. If I want to do a password, I can just type it in, but I want to encrypt this. So there is also this almost hidden path lock that you can press and then it will just hide the value from the screen. That's great at first, but it will also encrypt the value in the database in VSDS and it will not show in the output locks of your build. So then you're safe. If I now want to change this, if I save this and I want to change it back, it's never visible again. So I always have to fill it in again. So that is great. So I will just put this back. Then walking through the other stuff, I can run multiple configurations at the same time. For example, I want to do a release and a debug for different platforms. So I can add multipliers here. For example, do the build configuration in debug and release or any CPU on debug and release, X64 on debug and release, so you can add multipliers by using this format. So build platform, build configuration, and then it will just do all those builds together. You need multiple agents to do that, of course, because an agent can only run one build at the same time. So if you want to run in parallel, and that's an option that you can specify here, if you want to run in parallel, you need multiple agents available to run in, of course. Then there is create work item on failure. I think it's obvious. It will just create a bug when the build fills. And this one is very interesting. I also wrote a blog post on that. I wrote to ALM. This one is giving me an access token. So if I check this box, it will create automatically underwater a variable that's called system.accesstoken. And that access token can be used to access the rest APIs of VSTS. So if I want to do, for example, give me all the commits that are attached to the build I'm running now, because I want to do extra stuff on them, you can call the rest APIs of VSTS. But in order to be able to call the rest APIs of VSTS, you need to authenticate against the rest APIs. And because the build agents are just running on a machine and you don't know what, you need to log into that rest API. So if you press this button, it will provide me a token that has all the authentication details and I can just access the rest APIs by putting that token in the headers of my request and I can just get everything from the rest APIs. So that's very convenient. Otherwise, you have to write your own authentication stuffy inside your PowerShell and now you can just use this. So this is really, really useful. And you should, if you want to use it, look into that. And the repository, so that's nothing special again. So we can just change the repository where we are getting the sources from. And we have, of course, the triggers, the continuous integration trigger. It's just a checkbox. So every time when I check in into the repository that is attached to this build, so in my case, the Git repository, and it listens to the branch. So if something changes on this branch, this build will trigger and it will automatically run. And you can, of course, have scheduled builds at the same time. And that's something that is also new in opposite to the XAML builds. The XAML builds could only do one thing at the same time. So you could either do a continuous integration build and then you had to copy the build and do a scheduled build. And if you want to run two times a day, you had to copy the build again and then you can do another schedule. Now that is all different because we can just do everything at the same time and we can add multiple schedules if we like. So this is really handy to do just your build configuration. So let me just switch this off. What more about the general tab? Nothing more that you can change the build format, the build number format, and the retention policies that you have. So how long do I want to keep those builds? And nothing. That is very, very convenient, history, audit logs on the build definition. So I can perfectly see who changes, who changed the build definitions and why. So that's also very nice. So when I run this build, and I'm not going to do it because my time is getting really, is going really, really fast. But I also prepared something like this. When I run this build, and this one is a little bit more verbose maybe, so you can see all those things. So I run unit tests. So I can see my test results directly in my build report. I can see the code coverage. So that's also directly in the build report for the unit test that I'm running. I can add tags. So this is a really convenient way to set, for example, your build quality. This one, this build is ready for test, or this one, this build is ready for release, or whatever. And you can see the associated changes. So this build is, this commit is attached to this build. And if there are work items attached to that commit, they also show up here in the associated work items. What I really like about when a build, for example, failed is that you can also see the failed tests, and then the detailed report of the tests, they really, really show you nice information. So for example, this test, the validate shopping cart, it failed. When I click it, I have my error message directly in the screen. I can see the stack trace. So this is really rich information on this build definitions that you can also later on pin on a dashboard or whatever you want to do with it. So this is, yeah, the new build that is going, it's still expanding. So they are really now building the widgets for the release, the widgets for the test, so you can have a very, very rich build report. So that's great. So let's move on to release. The release is actually not very exciting after I told you all this stuff about build, because it runs on the exact same infrastructure. It has two separate teams, and there are differences, because that's how it works at Microsoft. They talk to each other, but they also have their own implementation of stuff. So there are tiny differences. For example, the rename, I have to do the rename here, and on the build, I have to right-click it and rename. So that's all the, that's the tiny stuff that, yeah, it frustrates me, but okay, it still works. It's not a tiny thing, but the big picture, it's all the same. So we have the new release definition, and we have the tasks here. And when you create a task, you can say it's available in build, or it's available in release, or in both. And I think that 95% of the tasks that are in the store right now are available on both. So if you look at this task, it's all the same. So it's, so you can just do the PowerShell, you can do deployments, you can run whatever you want, copy files, doing Azure stuff, creating resource groups on Azure, it's all there. So this one, for example, the Azure Resource Group Deployment, it's really powerful task. You can just edit, and then you can say, okay, I want to point to a subscription that you can manage by creating an endpoint. And then you can just point to a resource group and say, start all the virtual machines or stop all the virtual machines, or create me a new resource group based on this template. And it's just there, and it works on the water with the PowerShell stuff. An extra dimension that we have within my release pipeline is the environment. And I think personally that environment is a wrong term that they use inside the release definition. Because for me, environment implies that it's a bunch of machines that it's running on. Maybe it is, but actually it's more like a stage. It's something that I do in a specific stage of my pipeline. So in this case, when I go to the development stage, I want to deploy to this environment, and this environment is multiple servers. But when I've done that, I want to maybe move to the next stage where I do some copy or files, and creating a zip file, and maybe sending out some email or whatever. And that's not an environment. It's just a stage that I'm going through in my pipeline. So environment is something, is a group of tasks that you want to execute. And you can put validation and approval on that specific stage. So keep that in mind that it's not related to machines. It's more like the phase that you are going through. So I created four environments, development environment, QA, staging, and pre-production. And every environment has its own pipeline of steps. And luckily for us, you can clone those environments. So if I have similar ways of doing stuff on the dev, it's doing exactly the same thing as on acceptance. Only there are different values of the parameters. I can just clone the environments, and I have it directly. So that's all there. So in my dev environment, I just now do a website deployment. It's not really interesting because it takes the website that I created in my build, and it deploys that to a web application on Azure. How does it know to which build definition it should respond? When I create a new one, it asks me, but if I already created one, I can go to the artifacts step. And the artifacts are something that you really should keep in mind. Microsoft really split it, the responsibilities of build and release, where maybe Jenkins who uses Jenkins. Okay, so there is no relation there. But I think it's a nice story to know because Jenkins is a task runner. It's a build system, or it's a task runner. And in Jenkins, you can do everything. You can just schedule a job, and it just runs the job. And sometimes it builds, and sometimes it deploys, and sometimes it does something else. It doesn't really matter. Here in VSTS, they really made the responsibility of, okay, we have a build, and the build outputs an artifact, a package, a zip file, or an MSI. And the release takes that artifact and does do something with that. So deploy it to an environment or copy it to some machine or whatever. And that's something that you should really know. So it's not, you can do it probably, but you always need to build to have the artifacts, and then the release pipeline takes care of the rest. So in my case, I linked the release build to this release pipeline. And I can link multiple builds. So if I have 20 components, then I have maybe 20 builds. They all output an MSI. And then I have one release pipeline, and I attach all those MSI as an artifact to my release, and then I execute my deployments. So I attached this release build. So in my task, it asks me for the web deploy package. When I browse for this web deploy package, it shows me the linked artifacts. So this is something that I delivered inside my build. These are the artifacts of my build that I published, and I can point towards them. So this is just selected. There are other artifact stores, so I can point to a build. I can point to a Git repository. I can even point to Jenkins. So if I have a Jenkins server that is publicly available, so where I can get to, I can create a service endpoint to that Jenkins server, and I can get my artifacts from there. So then I can use release management without the builds in VSTS. So that is also very great if you're in transitioning, because you eventually are going to move over to this one. And then we have the variables, same as in the build. You can refer them as the same as the build. There are some other predefined variables that you can use, the release dot artifact directory and such thing. There is one catch here, a really, really bad UI. This release variables, it's actually a link. If I can click it, I can just switch to environment, and then I can see all my variables per environment. So this is also nice. Triggers, I can create a trigger manual. I can create a release manually, so I can start the release. I can also do continuous deployment, when my build finishes that is attached to this release, it automatically starts this release. So this is continuous deployment, and I can do scheduled releases as well. So I want to do the release every night at three o'clock, for example. And this one is also very interesting. This is quite new. These are environment triggers. So when are we going to trigger this release? Or this environment? So this, this environment, this one will trigger after release creation. So my deployment condition is after release creation. So when I press new release, it will start automatically executing the development environment. When I go to the, for example, QA environment, this one will trigger after another environment has finished, or it will trigger manually, for example. So this way, I can also do parallel stuff, because my QA environment says, okay, I want to trigger when the dev environment is ready. But on my staging environment, I also say, when dev environment is ready, I want to trigger this. So this one, this way you can just parallel deploy to multiple environments. And then you can come back, because of my production environment. There is say, it says, okay, you have to wait until QA and staging are ready, and then published to my production environment. So you can really create a nice flow of how your application moves through your infrastructure. So that is very nice to see. And on the general tab, we have just some simple stuff on the how does the release number looks like. And we also have a history trail here. Creating a release is quite easy. You can just create the release. You point to the build that you want to release, in this case. And then you just start running the release by create, and then it will automatically run. There is one thing that I missed, and that's, I think, the main advantage of using a release pipeline like this. We can add validation. So what we can do is we can assign approvers to a specific stage. So whereas a build just runs when you trigger it, in the release pipeline, it's different. We can say this stage must be approved by someone, by me. So before you do something, I want to set an email to this guy, and he has to approve that it's possible. So the first stage is most of the time not an approved stage. But the second stage, going to test, sometimes a product owner wants to say, OK, I want to do it. Or the testers say, OK, I want to do it now. And they can just approve the build. And you can approve pre-approved and post-approved. So when it's there, you can also say, OK, it's OK now. So in this case, we have approval. So when I start this release, and I point to this build, and I say create, it will not start automatically. But it has this little guy. And here it says, OK, you have to approve this specific release. And now it's waiting until the approval comes. So I will not run it, because I want to show you the last demo of the extensions. And I think that's cooler than looking at the output of a release that's just executing some scripts. So going back to build, because I showed you the builds, and I showed you how to add build steps. But I didn't show you that you have more build steps available than what's here. If you close this one out and you go to the shopping basket, you can browse the marketplace. The marketplace already contains a lot of build tasks that you can just click and install. If you do it, it will be available in your toolbox, and you can just add them to your pipeline. And there are already great extensions available, and they are really pushing the community to build them. So it will grow and grow. And you can also build them yourself. And that's what I quickly wanted to show you now. So what I did is I created a small build task. So this is my Git repo for that. And as you can see, it's very, very easy to do it, because there is only a VSS extension manifest, which is just a description of this task. What's the version? What's the description? How does my readme page look like? What are the background colors in the marketplace? Well, all that kind of configuration. Some licensing and overview, that's some documentation, some images, also not really relevant. We have a task manifest, which describes the task, what is the version of the task, and which PowerShell does it execute, on which agent should it run the minimum agent version, the demands. So if I need a curl or if I need Java, I can add it to my task manifest so that I can demand it from my build pipeline. And you can see that it writes the message here. And then we have, of course, the PowerShell script itself, which just simply, in this case, writes a message. So that's it. Then we have a tfx command line, which you can use. And with the tfx command line, you can package this directory into a VSIX. And at VSIX, you can upload to the marketplace where you have to be a publisher. So for that, I can show you the marketplace because I need, I have some issues with my account. I need another browser for it. Don't ask. It's Microsoft Identities. That's really failing me sometimes. So I have to click the work account. This is all the stuff that I already prepared on my laptop. But I don't have to sign in and stuff. So this is the marketplace. I have created one task that's available in the marketplace already. So that's sending email. And you can see that there is only one task. So this is publicly available. The other task that I created is really private available. Instead of running the command line, what I did is I created a build and used a task from a colleague of mine that just handles all the publishing stuff. So it replaces some variables. It replaces my version. It replaces the publisher. It replaces the public private availability. It takes care of all kinds of stuff. So I used that task. And it just says, okay, take this Git repo, package it into a VSIX and upload it to the marketplace. So when I run this build, it will hopefully do that. Now it's running on the Docker agent. That's not nice. So let's try that again. So it's now running on my machine because it needs TFX. And it has some demands that are not handled correctly, probably. So that's feedback that I'm going to give him. Take care of your demands. So it's now publishing to the marketplace. Setting the version. Okay. So when I refresh this, I have this write message. Task available in my marketplace. And it's shared with one account. In my case, my own account. So moving to a build that I already prepared for this, the write message demo. I can now go to manage extensions. And then this write message task that I created with this nice NDC Oslo logo. I can click it and I can install it into my account. So I will just hit and continue. So it's now installing. And then it says proceed to account. So it might be possible that I have to restart my browser because there is sometimes a little lag in the tasks. But hopefully it will do. So if I now edit my build definition, okay, I already added it so it was disappeared because I removed it. But in my toolbox on utility, there is this write message task that I created that's only available on this account because it's private and shared with this account. And I can share with multiple accounts if I like. So during development, it's nice to have that for your own organization or only keep it for your own organization because you don't have to make it public. Then it's only then it's for everybody. And sometimes you have specific stuff that you want to run for your organization. So I created this message and I already put in a variable for that message. And then I can queue the build. That's the last step of my presentation. So before I do that, I want to tell you that I'm available today on the conference. So if you have any questions, if you want to see more, just find me and I can show you everything that you like. I hope that you enjoyed the session. Excuse me for that. It was a little bit of noisy in the beginning, but you can imagine the stress that I had for the laptop stuff. So thanks for your patience. Thanks for being here. And now I'm going to run this build. And hopefully it will just start. And show some nice output that I created for you. So to clone my repository, that's exciting. Find a decent internet connection when you're doing Fiestes. So that's it. Thank you very much. Thank you.
 Welcome. I understand fully that it was a party last night. So thank you for being here so  early at nine o'clock. There is not much people. I think that most of them are still in bed  sleeping. So let me start with a short introduction. I have two laptops here. And that's why I came  here this morning at eight o'clock. Started down my laptop. And now it says this. Updating  Windows. So all the demo preparations that I did. Nice presentation. Nice Spotify playlist.  Nice demos. It's going to be a little bit different now, I think. So I have the laptop  of my colleague. My other laptop is at 88%. So I have good hopes that during this session  it will come up again. I have some demos that I can only do on this one because I prepared  it here. But most of the stuff that I'm going to show you is in the cloud. It's on Visual  Studio Team Services. That's a cloud service. And it's on Azure. It is also a cloud service.  So I think I can manage a whole lot to show you today. So that's what I'm going to do.  This PowerPoint online, that's my only slide. So I will close this down. And then I will  just start because I thought it was nice to have a demo-only session. So first I want  to introduce myself. My name is Sriné van Osnabrige. I'm a lead consultant at XperiaT  in the Netherlands. We are a firm that consults in ALM, in Azure, in Cloud and mobile. And  I help companies in proving their software processes. So I really look broadly to people,  as in tools. And my expertise is Visual Studio Team Services and Team Foundation Server.  I'm an ALM MVP as well. And this photo was taken at Build. So I also have the HoloLens  part in my session. There is also that HoloLens session next to me. So all the other people  that are not in bed are probably there. So this was a great experience that I had there.  And I can really recommend everybody to just, if you have the chance, just try it out because  it's really, really awesome. Then in private I have a wife and two kids. My oldest is five  and my youngest is two. Yesterday, two days ago, he was two. And that's it. I like to  run sometimes. So without further ado, I want to just start with the demos. And then let  me start my timer. Otherwise, I will just hopelessly run out of time. So first question,  who works with VSTS already? Okay. Okay. And who works with the build and release management  system already? Oh, okay. And then I hope that I can tell you some new stuff. So this  is the intro page. So this is the dashboard. You can create all kinds of widgets and you  can create your own stuff and you can put everything on there. So it's more a dashboard  for entry point of VSTS. And there is also the work hub where we did what, which we can  use to do some work on the management. So to walk you through what I'm, what we are  going to do today, I created a small backlog. I already did the preparation, but not properly  because my laptop crashed and was updating. I already did the introduction and I'm going  to do the agenda. So what I'm going to do today, I'm not going to show you all the build  steps that are in the box. I'm not going to do, okay, this build step can do that and  this build step can do that. I want to really dive into what is build and release management,  what are the conceptual things behind it? How do the agents work? How does the infrastructure  work? How does the cross-platform build agents work, which only run on that machine? So I  can show you the stuff that is really below the surface because all the tasks, it's really  situational and it depends on the situation that you're in, what and how you are going  to use it. So that's what we are going to do. First, then we are going to set up a build.  We'll talk a little bit about, sorry, I will talk a little bit about setting up tests,  updating, et cetera, et cetera, capabilities and demands, triggers, et cetera. Then we  walk into VSTS release management, which you can see it's quite similar as the build  system. Only you have the approval and validation parts in there as well. And then lastly, if  my laptop works again, we can do some customization and extensions and I can show you how that  works and I will show you a co-extension. Before I continue, my laptop is responding  again. I can log in. So if everything works here, I can just start. So I can start with  a simple demo here and then I can maybe move over. So first of all, I move to the build  tab. This is where everything happens. So as you know or might not know, Microsoft had  first exam build engine. Who used the exam build engine? Who liked it? So I think that  the main reason why people use Jenkins and TeamCity was because of the exam build engine.  It really was bad. It was, you could do stuff, but if you wanted to do something a little  bit different than what was out of the box provided, you came into customization and  that was really, really hard. You had to build assemblies and you had to put them in source  control and you had to configure your controllers and it was really, really hard to do. So Microsoft  understood that and they said, okay, we are going to build a new build engine. We are  going to build an engine that is easily customizable, that can easily be extended and that is very,  very lightweight to run. And that's what they did. And I think, and I use Jenkins at my  assignment right now and I think it's better. I think it's really, really good. It's really  fast and it's really handy in use. So let me just start with a simple build definition.  When I press create new build definition, I can select templates. And what is a template?  It's just a blueprint of something that I already did or what is provided out of the box by  Microsoft. And as you can see here, it's not only a Microsoft based templates. You can  see Android. You can see and, you can see Gradle. You can see Maven. So it's not only  Microsoft related stuff that you can do. You can also do non-Microsoft related stuff. This  is really great. So you have also deployment templates, which is nothing more than a build  template with some build steps in there that can do deployment stuff. And I can have custom  templates. So you can create your own template. For example, for your own components that  has certain steps that you always want to follow or certain build numbers that has a  certain format. And you can just save those templates and you can just create them from  here. And then I can just say next. And then I will have this template as a base. Then  I can select a repository. The repository is not only VSTS. You can select a VSTS repository  and then I can select both. I can select a TFVC, so Team Foundation Virtual Control  repository that resides in the same project or I can select a Git repository. What else  I can do is I can move to GitHub. I can create a service endpoint to GitHub and I can extract  my sources directly from GitHub and use the build engine of Microsoft in VSTS to just  build my sources from GitHub directly. There is also the remote Git repository, which is  just somewhere and subversion. Who uses subversion? So I don't know why it's there. I think that  just good. So I select a repository. I select the default branch that I'm building and I  can select the agent which I'm running on. So I come back to agents a little bit later,  but this is now the hosted agent. So Microsoft has a pool of agents somewhere in the cloud  that you can just use. So if you don't have fancy stuff to do and you don't want to set  up infrastructure, you can just point to it, to the hosted pool and Microsoft provides  the agents for you. So I can create. And then first thing I need to do is I can create a  build step. A build step is a simple lightweight zip file. You should see it as a zip file which  creates which has a manifest which describes the task. So you can see the name and the  title and the input parameters and stuff. And it contains a PowerShell script or Node.js  script, which is executed when you execute the build step. Microsoft is moving to Node  and to.NET Core because that's cross platform. If you use PowerShell, it can only run on  Windows based machines, of course. And if you use Node or you use.NET Core, you can  use the same build tasks on multiple platforms. So Microsoft is really moving all their tasks  to the new infrastructure. But most of them now are still in PowerShell and you can see  the variants there. So let me just start by adding a simple PowerShell. And I can hit  close. So I add a PowerShell script. I can choose whether I want to use inline or file  path. And then I can just write some PowerShell script. So let me just be simple and easy.  And I can just say hello, NDC. Save the template. I can give it the name. So let me just say  first look build, for example. Okay. And then I just queue the build. So really simple.  If I can, if I selected the template with contain more steps, it was somewhat more configuration.  But I can just now hit enter. And now it will just start up my build. It will look in the  hosted pool for an available agent. And what you see sometimes is if it's a little bit  more busy, it takes a few seconds to just get an agent that is available to run my build.  And then it's running. So what you see here is hello, NDC. So that's the output of my  PowerShell script. Nothing fancy here. So let's dive a little bit further. For example,  if I add another build step. And a PowerShell script. Make it inline again. And I just say,  for example, I want to do a curl statement. So I want to do curl, HTTP, Google.com. And  I will save this. If I queue the build now, it will, of course, run my first PowerShell  script again. But what we'll see is that it will probably not run on the hosted agent.  It will crash. And this is what I mean by it takes a while sometimes to connect to the  hosted agent. So you will see it crashes. Why? Because on the hosted agent, curl is not installed.  So the hosted agent does not contain everything you want. It contains the basic stuff. It  contains the.NET frameworks and everything that you can expect from a Windows agent or  a Linux agent. But it doesn't contain the tools that you need sometimes. So you can  do two things. You can either provide the tools that you need by putting the XE files  that you need to run curl, for example, and just copy it to the agent. And then execute  that XE to do your thing on the hosted agent. Or you can run a on-premise agent. And that's  what we are going to do. And my laptop works. So I'm going to switch machines. And then  I'm going to come to show you on this laptop. So give me a sec. Okay.  So I opened up the build that we just created. And what I want to do now, I want to switch  to my on-premise agent. So for that, I'm going to the general tab. And I go to the default  agent queue. And I press manage. Okay. I need to maybe connect. Yeah. So here we are. So  in my management, I have queues. I have a default queue. I have multiple queues. And I have this  hosted queue. So the hosted agent is always online. If this one is red, something is wrong  at Microsoft. So we cannot do anything about it. This is always green. So we have the default  pool. And we can create all kinds of agents in here. So what do we do? We can download  an agent. If I press this one, and I won't do it for the time that I lost, it will download  a zip file for me. And that zip file contains some files. You unblock the file. Very, very  important to unblock the file. And then you extract the file to your local disk. So when  I go to my command line, I have a NDC agent. So this is what it kind of looks like. So  you have the agent directory in configure and run. That is what you initially get when  you extract the file. Then you are going to configure the agent. So what that does, it  wants to know to which collection am I connecting. How is this agent called, et cetera, et cetera.  So it will now hopefully start connecting. Maybe I should switch back to the other machine.  I'll show you.  Okay, let's try something different.  I will just try to download the agent again.  So I will download the agent.  I think the network connection is a little bit slow.  This is the agent that I downloaded.  So I will just copy this one.  Create a new folder, NDCA.  Extract it here.  And let's try to do this one.  I don't know why this is not working.  Ah, okay.  So I have to configure the agent.  So I can say the name of the agent, the name of my server that I'm connecting to,.com,  the pool to which I'm connecting.  So you can create pools of agents, and you can share those pools amongst different collections  that you have.  In VSTS, you only have one collection, and one collection can have a pool, and you can  attach a queue to a pool.  If you have multiple collections, you can create another queue on another collection  and connect it to the same pool.  So that's how you can share your built infrastructure in your organization.  If you used the XAML builds before, you had a build controller and a build controller ran  on a machine, and it connected to one single collection.  If you had another collection that you also wanted to use for your builds, you had to  create a new machine with a new build controller.  So it was not really scalable to use your build infrastructure.  So instead, we can now share built queues.  So I'm connecting to a build queue.  Where do I want to get my sources?  And I can say, where do you want to run this service as a Windows service, or do you just  want to keep running in your console?  What I usually do is I don't use the hosted agent much.  Most of the time, just run in my console on my local machine.  So when I'm doing building builds, creating builds, I just run a console and testing the  builds because then it gets all the sources that I'm doing on my local machine, and I  can easily debug.  I can easily do stuff on the sources that it gets.  I know what happens exactly because it's on my machine.  And once it's running, I just will run on the build agent somewhere in our build infrastructure.  So that's a really convenient way to just easily start up a new build agent or multiple  build agents at the same time.  So now I will just connect to my thing here.  So I will sign into my account.  So this build agent without firewall stuff, it connects to the default ports.  It will connect to my VSTS account, and it will just start running.  So here it's running, and in my...  I had to start up somewhere here as well.  That's all the preparations that I missed.  So here you can see that I have the RVO Dell 2.  Just the agent that I just started up, it's now running on this machine as well.  I will just...  Can I just remove this one?  No.  So when I go back to this build, and if you still remember because of all the do, we did  a curl statement on this build.  When I queue this build, I can say I want to run on the default queue.  So not on the queue in the cloud, but on the default queue, and I can run.  VSTS starts the build.  It puts it in a queue.  The queue finds an available agent, and then it starts to run the build.  And you can see that it finds the RVO Dell 2 agent because that's now the only agent  that is available because the other agent on that machine that I used before, I disabled  that.  Now I finally find one agent, so it will run there.  So it will get sources, and then it will execute the PowerShell script twice, hopefully.  Okay.  Not recognized.  So probably I did something wrong in the...  OK, OK.  Thanks.  Yeah.  So, but when I do this, it will run and it will show me the output of the crawl statement.  That's not very interesting.  But what is interesting is, so let me change this back so that it is default on the default  queue and let me then quickly change this as well for the next run.  What is interesting is that, obviously, when I run a build, sometimes it happens that my  agents are not capable of running that build because they don't have the tools that I need  to run that build.  So how can I manage that?  How can I make that controllable?  We can do that by adding demands.  So on this general tab, I also have demands.  This demand means that I can say, I want to be something present on the build server when  I run this specific build definition.  I can say, for example, I want curl to be present.  Curl must exist on this build agent.  I can save.  This is a manual step, so I can add anything that I want.  So if I can sort of like tag my agents and tag my builds, so this build is a update to  build and this build is a legacy build.  So I can do all the demands.  But there are also tasks that you can add.  For example, there is a task gradle that I can add.  And this gradle task, it automatically adds to the month Java.  So if, oh, okay, sorry, if I want to run a gradle, it demands that Java is installed on  the machine that I'm running on.  So the task is configured to add that demand automatically.  So let me just quickly remove that.  When I run the build now, it tells me there is no agent that is capable of running this  build.  It demands curl, but there is no agent with curl.  So sorry, you can queue it and wait forever or you can just fix it.  So what we are going to do, of course, is trying to fix that.  If I move to my agent that I just created, there is a tab, capabilities.  So demands and capabilities, they are a pair.  I demand something and my agent should have that capability to be able to run that.  So what you can see here is that there are system capabilities.  So Chef, DNX, Java, that's all system environment variables on my system.  These are the tools that I have installed on my systems and it just reads the environment  variables and it knows that Java is installed.  If I need something extra, I can just say curl.  And for example, one or true, I don't care because I just checked that curl exists.  So if I save the changes here and I run this build again, then it will automatically queue  and it will find an agent and it will only run on agents that have that curl capability  configured on true.  So it will now hopefully run and even run without errors because I just fixed it.  So here is the curl output.  So this is all the queue and the pool and how can you manage your build agents with  demands and capabilities.  So this is how you can steer your builds in your build infrastructure.  This is not cross-platform yet.  So what I want to show you now is I want to do the same thing for the build but run on  a Linux-based agent.  So when we create a new build definition and I will just do an empty build definition  again, I will just select my NDC project, create, and I add a build step.  But I'm not adding a PowerShell script but I'm adding a shell plus plus script.  So this is the Linux-based thing to run PowerShell, for example, or command line.  So I can just say echo as well NDC and if we look at the demands, it demands SH.  It demands shell to be present on the agent that I'm running on.  So if I press save now and I would just say Linux, save and I queued this build, I don't  have an agent.  I don't have a Linux agent running yet.  So we are going to fix that.  So I have a Linux machine running in the cloud and I need to quickly look up my password  here.  So this is a Linux machine.  And what I can do is I can, of course, download the agent on this Linux machine, which I did.  So there is a build agent here.  But on Linux, we can do other stuff as well.  We can also say we are going to run Docker because Docker is a very, very lightweight  virtual machine-like thing.  Who knows Docker, the concepts?  Yeah?  Okay.  So instead of installing the agent on the machine, because the machine has all the environment  variables, I have a specific version of Java and I have a specific version of whatever,  node.  Then I can only have agents that run on that specific version of software.  While when I create virtual machines, I can have many virtual machines with agents installed  and run different versions of software on that.  So I can sometimes run with Java 7 and sometimes run with Java 8 or whatever.  But if I do it in Docker, it's all the benefits of the virtual machine, but still smaller  and very easy to roll out.  So what I did is I created a Docker image that's called xperia.vsts build agent that  has node installed.  It's just a Docker container with a build agent configured and installed already, but it's  not running yet.  So if I'm going to run this container by saying, Docker run, minty i xperia slash fsts build  agent bash, it will start up the container and you can see how quickly it is because  it's already done.  And then I can see the agent directory here.  So I will go into there.  And then I will come, I can say, switch user because I cannot run this service sa root  user.  That's not allowed on Linux.  So I have to switch to another user.  And then I can just say, run.  It asks me for my username to connect.  I already configured this agent to look at my collection.  I run and you can see it's just easy starting up this container.  And I can also do it by Docker run that it automatically starts up the agent already because  then you don't have to configure it manually, but this just for demo purposes.  So when I look now, I have a Docker agent running as well.  So when I queue this build now, it will go to the same queue and finds me an agent that  has SH installed.  And that is, in this case, my Docker agent.  And then it will just automatically pop up my NDC message here as well.  So you can imagine, and I won't show you now because I want to save a little bit time,  that if I just exit this container and say, okay, I now want to run another container  with a Java version 8 installed and I'm doing a Java build which demands me a Java installation.  I can just easily start up a new container.  For example, the VSTS build agent Java, it automatically pops up and the whole infrastructure  makes sure that it will run on the container that is capable of running that specific  build.  So I did two blog posts on build agents in Docker containers, both on Linux and Windows  because Windows is also now capable of running Docker containers in a preview mode.  So you can look at road2alm.com and there are two blog posts there that describe how  to do this.  It's really convenient way to just quickly start up new agents and do some configuration  there.  So that's really great.  So leaving my Linux build for what it is because after all, I'm still a Windows guy.  Let us walk to the rest of this build possibilities.  So I opened up the wrong one.  So let me open up this one.  So let me walk you through a template.  So if I choose the template Visual Studio build, it will provide me this template.  So it will do some Nuke at restore.  It will do a Visual Studio build.  It will run some unit tests that it can find.  It will publish symbols.  And then I added two tasks, copy files, which is more or less create a nice structure for  your build drops.  So you can publish artifacts to your build.  But if you do nothing, it will just publish everything that's in the binary directories  and you have everything.  But if you want to have nice folders, for example, I want to folder with my website  and I want to have a folder with my tests and I want to have a folder with my other components,  you can use the copy files tasks to just copy everything to a sub directory.  And then at the end, you can just publish the whole lot as a build artifact to the build.  So that's what I did.  If I am going to look at the solution, then what you will see is that we have values in  the MS build arguments.  And for me, this is was that there was something to get used to.  But because normally when you use the XAML builds, you just said, OK, I want to build  this solution.  And then you had some checkboxes like I want to do code analysis.  And I want to do I want to create an MS deploy file.  And it was just checkboxes and then you could run and then you had it.  The new build agent, it is very lightweight and it does not really things for you.  There are steps that can be created that does the stuff.  But it's doing nothing automatically.  So if we want to do visual studio build, and in my case, I'm building a website and I want  to provide, I want to, I want to copy a zip file.  I want to create an MS deploy zip file that contains my website.  I have to do some MS build magic.  So you have to know MS build a little bit more than you maybe did before when using the other  stuff.  You have to know what's happening inside MS build, what MS build needs to be able to  do the stuff.  So in this case, I want to do a web deployment.  So I have to add the parameters deploy on build, web publish method, package as a single  file.  And I also have this one run code analysis.  First it was just a checkbox run the code analysis and then underwater it's called MS  build with this parameter.  If you don't now want to run code analysis, you just have to specify this parameter and  then it will run it automatically for you.  And then you have the package location and this one is maybe a special value.  This is the build.staging directory.  So the dollar bracket open value.  What's that?  That's a variable that you can use within the build pipeline.  So let us move to the variables tab.  If I look at the variables, first start with the predefined variables.  There are lots of them that you can just use in your build pipeline.  So for example, the build directory, the home directory, what's the name of the agent that  I'm running on?  What's the name of the, what's the path of my artifact location?  What's the path of my source location?  What's the path of my binary location, et cetera, et cetera.  All those variables are present and you can reference those variables in all the steps  by just putting dollar sign, bracket open, name of the variable, bracket close.  When running PowerShell, it just injects them as environment variables and you can refer  to them by column and then the name of the variable.  So that's really useful.  You have all those variables always at your servers.  So you can also, of course, create your own variables.  So just add a new one, give it a name and give it a value.  For example, password.  Let me do that.  If I want to do a password, I can just type it in, but I want to encrypt this.  So there is also this almost hidden path lock that you can press and then it will just hide  the value from the screen.  That's great at first, but it will also encrypt the value in the database in VSDS and it will  not show in the output locks of your build.  So then you're safe.  If I now want to change this, if I save this and I want to change it back, it's never visible  again.  So I always have to fill it in again.  So that is great.  So I will just put this back.  Then walking through the other stuff, I can run multiple configurations at the same time.  For example, I want to do a release and a debug for different platforms.  So I can add multipliers here.  For example, do the build configuration in debug and release or any CPU on debug and  release, X64 on debug and release, so you can add multipliers by using this format.  So build platform, build configuration, and then it will just do all those builds together.  You need multiple agents to do that, of course, because an agent can only run one build at  the same time.  So if you want to run in parallel, and that's an option that you can specify here, if you  want to run in parallel, you need multiple agents available to run in, of course.  Then there is create work item on failure.  I think it's obvious.  It will just create a bug when the build fills.  And this one is very interesting.  I also wrote a blog post on that.  I wrote to ALM.  This one is giving me an access token.  So if I check this box, it will create automatically underwater a variable that's called system.accesstoken.  And that access token can be used to access the rest APIs of VSTS.  So if I want to do, for example, give me all the commits that are attached to the build  I'm running now, because I want to do extra stuff on them, you can call the rest APIs  of VSTS.  But in order to be able to call the rest APIs of VSTS, you need to authenticate against  the rest APIs.  And because the build agents are just running on a machine and you don't know what, you  need to log into that rest API.  So if you press this button, it will provide me a token that has all the authentication  details and I can just access the rest APIs by putting that token in the headers of my  request and I can just get everything from the rest APIs.  So that's very convenient.  Otherwise, you have to write your own authentication stuffy inside your PowerShell and now you  can just use this.  So this is really, really useful.  And you should, if you want to use it, look into that.  And the repository, so that's nothing special again.  So we can just change the repository where we are getting the sources from.  And we have, of course, the triggers, the continuous integration trigger.  It's just a checkbox.  So every time when I check in into the repository that is attached to this build, so in my case,  the Git repository, and it listens to the branch.  So if something changes on this branch, this build will trigger and it will automatically  run.  And you can, of course, have scheduled builds at the same time.  And that's something that is also new in opposite to the XAML builds.  The XAML builds could only do one thing at the same time.  So you could either do a continuous integration build and then you had to copy the build and  do a scheduled build.  And if you want to run two times a day, you had to copy the build again and then you  can do another schedule.  Now that is all different because we can just do everything at the same time and we can  add multiple schedules if we like.  So this is really handy to do just your build configuration.  So let me just switch this off.  What more about the general tab?  Nothing more that you can change the build format, the build number format, and the retention  policies that you have.  So how long do I want to keep those builds?  And nothing.  That is very, very convenient, history, audit logs on the build definition.  So I can perfectly see who changes, who changed the build definitions and why.  So that's also very nice.  So when I run this build, and I'm not going to do it because my time is getting really,  is going really, really fast.  But I also prepared something like this.  When I run this build, and this one is a little bit more verbose maybe, so you can see all  those things.  So I run unit tests.  So I can see my test results directly in my build report.  I can see the code coverage.  So that's also directly in the build report for the unit test that I'm running.  I can add tags.  So this is a really convenient way to set, for example, your build quality.  This one, this build is ready for test, or this one, this build is ready for release,  or whatever.  And you can see the associated changes.  So this build is, this commit is attached to this build.  And if there are work items attached to that commit, they also show up here in the associated  work items.  What I really like about when a build, for example, failed is that you can also see the  failed tests, and then the detailed report of the tests, they really, really show you  nice information.  So for example, this test, the validate shopping cart, it failed.  When I click it, I have my error message directly in the screen.  I can see the stack trace.  So this is really rich information on this build definitions that you can also later on  pin on a dashboard or whatever you want to do with it.  So this is, yeah, the new build that is going, it's still expanding.  So they are really now building the widgets for the release, the widgets for the test,  so you can have a very, very rich build report.  So that's great.  So let's move on to release.  The release is actually not very exciting after I told you all this stuff about build,  because it runs on the exact same infrastructure.  It has two separate teams, and there are differences, because that's how it works at Microsoft.  They talk to each other, but they also have their own implementation of stuff.  So there are tiny differences.  For example, the rename, I have to do the rename here, and on the build, I have to right-click  it and rename.  So that's all the, that's the tiny stuff that, yeah, it frustrates me, but okay, it still  works.  It's not a tiny thing, but the big picture, it's all the same.  So we have the new release definition, and we have the tasks here.  And when you create a task, you can say it's available in build, or it's available in release,  or in both.  And I think that 95% of the tasks that are in the store right now are available on both.  So if you look at this task, it's all the same.  So it's, so you can just do the PowerShell, you can do deployments, you can run whatever  you want, copy files, doing Azure stuff, creating resource groups on Azure, it's all there.  So this one, for example, the Azure Resource Group Deployment, it's really powerful task.  You can just edit, and then you can say, okay, I want to point to a subscription that you  can manage by creating an endpoint.  And then you can just point to a resource group and say, start all the virtual machines  or stop all the virtual machines, or create me a new resource group based on this template.  And it's just there, and it works on the water with the PowerShell stuff.  An extra dimension that we have within my release pipeline is the environment.  And I think personally that environment is a wrong term that they use inside the release  definition.  Because for me, environment implies that it's a bunch of machines that it's running on.  Maybe it is, but actually it's more like a stage.  It's something that I do in a specific stage of my pipeline.  So in this case, when I go to the development stage, I want to deploy to this environment,  and this environment is multiple servers.  But when I've done that, I want to maybe move to the next stage where I do some copy  or files, and creating a zip file, and maybe sending out some email or whatever.  And that's not an environment.  It's just a stage that I'm going through in my pipeline.  So environment is something, is a group of tasks that you want to execute.  And you can put validation and approval on that specific stage.  So keep that in mind that it's not related to machines.  It's more like the phase that you are going through.  So I created four environments, development environment, QA, staging, and pre-production.  And every environment has its own pipeline of steps.  And luckily for us, you can clone those environments.  So if I have similar ways of doing stuff on the dev, it's doing exactly the same thing  as on acceptance.  Only there are different values of the parameters.  I can just clone the environments, and I have it directly.  So that's all there.  So in my dev environment, I just now do a website deployment.  It's not really interesting because it takes the website that I created in my build, and  it deploys that to a web application on Azure.  How does it know to which build definition it should respond?  When I create a new one, it asks me, but if I already created one, I can go to the artifacts  step.  And the artifacts are something that you really should keep in mind.  Microsoft really split it, the responsibilities of build and release, where maybe Jenkins  who uses Jenkins.  Okay, so there is no relation there.  But I think it's a nice story to know because Jenkins is a task runner.  It's a build system, or it's a task runner.  And in Jenkins, you can do everything.  You can just schedule a job, and it just runs the job.  And sometimes it builds, and sometimes it deploys, and sometimes it does something else.  It doesn't really matter.  Here in VSTS, they really made the responsibility of, okay, we have a build, and the build outputs  an artifact, a package, a zip file, or an MSI.  And the release takes that artifact and does do something with that.  So deploy it to an environment or copy it to some machine or whatever.  And that's something that you should really know.  So it's not, you can do it probably, but you always need to build to have the artifacts,  and then the release pipeline takes care of the rest.  So in my case, I linked the release build to this release pipeline.  And I can link multiple builds.  So if I have 20 components, then I have maybe 20 builds.  They all output an MSI.  And then I have one release pipeline, and I attach all those MSI as an artifact to my  release, and then I execute my deployments.  So I attached this release build.  So in my task, it asks me for the web deploy package.  When I browse for this web deploy package, it shows me the linked artifacts.  So this is something that I delivered inside my build.  These are the artifacts of my build that I published, and I can point towards them.  So this is just selected.  There are other artifact stores, so I can point to a build.  I can point to a Git repository.  I can even point to Jenkins.  So if I have a Jenkins server that is publicly available, so where I can get to, I can create  a service endpoint to that Jenkins server, and I can get my artifacts from there.  So then I can use release management without the builds in VSTS.  So that is also very great if you're in transitioning, because you eventually are going to move  over to this one.  And then we have the variables, same as in the build.  You can refer them as the same as the build.  There are some other predefined variables that you can use, the release dot artifact  directory and such thing.  There is one catch here, a really, really bad UI.  This release variables, it's actually a link.  If I can click it, I can just switch to environment, and then I can see all my variables per environment.  So this is also nice.  Triggers, I can create a trigger manual.  I can create a release manually, so I can start the release.  I can also do continuous deployment, when my build finishes that is attached to this  release, it automatically starts this release.  So this is continuous deployment, and I can do scheduled releases as well.  So I want to do the release every night at three o'clock, for example.  And this one is also very interesting.  This is quite new.  These are environment triggers.  So when are we going to trigger this release?  Or this environment?  So this, this environment, this one will trigger after release creation.  So my deployment condition is after release creation.  So when I press new release, it will start automatically executing the development environment.  When I go to the, for example, QA environment, this one will trigger after another environment  has finished, or it will trigger manually, for example.  So this way, I can also do parallel stuff, because my QA environment says, okay, I want  to trigger when the dev environment is ready.  But on my staging environment, I also say, when dev environment is ready, I want to trigger  this.  So this one, this way you can just parallel deploy to multiple environments.  And then you can come back, because of my production environment.  There is say, it says, okay, you have to wait until QA and staging are ready, and then published  to my production environment.  So you can really create a nice flow of how your application moves through your infrastructure.  So that is very nice to see.  And on the general tab, we have just some simple stuff on the how does the release number  looks like.  And we also have a history trail here.  Creating a release is quite easy.  You can just create the release.  You point to the build that you want to release, in this case.  And then you just start running the release by create, and then it will automatically  run.  There is one thing that I missed, and that's, I think, the main advantage of using a release  pipeline like this.  We can add validation.  So what we can do is we can assign approvers to a specific stage.  So whereas a build just runs when you trigger it, in the release pipeline, it's different.  We can say this stage must be approved by someone, by me.  So before you do something, I want to set an email to this guy, and he has to approve  that it's possible.  So the first stage is most of the time not an approved stage.  But the second stage, going to test, sometimes a product owner wants to say, OK, I want to  do it.  Or the testers say, OK, I want to do it now.  And they can just approve the build.  And you can approve pre-approved and post-approved.  So when it's there, you can also say, OK, it's OK now.  So in this case, we have approval.  So when I start this release, and I point to this build, and I say create, it will not  start automatically.  But it has this little guy.  And here it says, OK, you have to approve this specific release.  And now it's waiting until the approval comes.  So I will not run it, because I want to show you the last demo of the extensions.  And I think that's cooler than looking at the output of a release that's just executing  some scripts.  So going back to build, because I showed you the builds, and I showed you how to add build  steps.  But I didn't show you that you have more build steps available than what's here.  If you close this one out and you go to the shopping basket, you can browse the marketplace.  The marketplace already contains a lot of build tasks that you can just click and install.  If you do it, it will be available in your toolbox, and you can just add them to your  pipeline.  And there are already great extensions available, and they are really pushing the community  to build them.  So it will grow and grow.  And you can also build them yourself.  And that's what I quickly wanted to show you now.  So what I did is I created a small build task.  So this is my Git repo for that.  And as you can see, it's very, very easy to do it, because there is only a VSS extension  manifest, which is just a description of this task.  What's the version?  What's the description?  How does my readme page look like?  What are the background colors in the marketplace?  Well, all that kind of configuration.  Some licensing and overview, that's some documentation, some images, also not really relevant.  We have a task manifest, which describes the task, what is the version of the task, and  which PowerShell does it execute, on which agent should it run the minimum agent version,  the demands.  So if I need a curl or if I need Java, I can add it to my task manifest so that I can  demand it from my build pipeline.  And you can see that it writes the message here.  And then we have, of course, the PowerShell script itself, which just simply, in this  case, writes a message.  So that's it.  Then we have a tfx command line, which you can use.  And with the tfx command line, you can package this directory into a VSIX.  And at VSIX, you can upload to the marketplace where you have to be a publisher.  So for that, I can show you the marketplace because I need, I have some issues with my  account.  I need another browser for it.  Don't ask.  It's Microsoft Identities.  That's really failing me sometimes.  So I have to click the work account.  This is all the stuff that I already prepared on my laptop.  But I don't have to sign in and stuff.  So this is the marketplace.  I have created one task that's available in the marketplace already.  So that's sending email.  And you can see that there is only one task.  So this is publicly available.  The other task that I created is really private available.  Instead of running the command line, what I did is I created a build and used a task  from a colleague of mine that just handles all the publishing stuff.  So it replaces some variables.  It replaces my version.  It replaces the publisher.  It replaces the public private availability.  It takes care of all kinds of stuff.  So I used that task.  And it just says, okay, take this Git repo, package it into a VSIX and upload it to the  marketplace.  So when I run this build, it will hopefully do that.  Now it's running on the Docker agent.  That's not nice.  So let's try that again.  So it's now running on my machine because it needs TFX.  And it has some demands that are not handled correctly, probably.  So that's feedback that I'm going to give him.  Take care of your demands.  So it's now publishing to the marketplace.  Setting the version.  Okay.  So when I refresh this, I have this write message.  Task available in my marketplace.  And it's shared with one account.  In my case, my own account.  So moving to a build that I already prepared for this, the write message demo.  I can now go to manage extensions.  And then this write message task that I created with this nice NDC Oslo logo.  I can click it and I can install it into my account.  So I will just hit and continue.  So it's now installing.  And then it says proceed to account.  So it might be possible that I have to restart my browser because there is sometimes a little  lag in the tasks.  But hopefully it will do.  So if I now edit my build definition, okay, I already added it so it was disappeared because  I removed it.  But in my toolbox on utility, there is this write message task that I created that's only  available on this account because it's private and shared with this account.  And I can share with multiple accounts if I like.  So during development, it's nice to have that for your own organization or only keep it  for your own organization because you don't have to make it public.  Then it's only then it's for everybody.  And sometimes you have specific stuff that you want to run for your organization.  So I created this message and I already put in a variable for that message.  And then I can queue the build.  That's the last step of my presentation.  So before I do that, I want to tell you that I'm available today on the conference.  So if you have any questions, if you want to see more, just find me and I can show you  everything that you like.  I hope that you enjoyed the session.  Excuse me for that.  It was a little bit of noisy in the beginning, but you can imagine the stress that I had  for the laptop stuff.  So thanks for your patience.  Thanks for being here.  And now I'm going to run this build.  And hopefully it will just start.  And show some nice output that I created for you.  So to clone my repository, that's exciting.  Find a decent internet connection when you're doing Fiestes.  So that's it.  Thank you very much.  Thank you.
A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_0_59.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_60_131.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_132_503.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_504_599.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_600_671.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_672_839.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_840_899.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_900_2231.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_2232_3695.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_3696_4247.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_4248_15983.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_15984_16427.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_16428_16499.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_16500_16583.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_16584_20015.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_20016_20459.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_20460_21611.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_21612_22739.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_22740_23747.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_23748_23999.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_24000_24059.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_24060_24431.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_24432_24587.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_24588_25631.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_25632_25763.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_25764_25919.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_25920_26183.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_26184_26279.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_26280_28499.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_28500_30095.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_30096_30503.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_30504_30659.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_30660_30839.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_30840_31679.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_31680_32267.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_32268_32399.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_32400_32927.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_32928_35063.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_35064_35195.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_35196_35339.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_35340_35387.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_35388_37667.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_37668_38147.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_38148_38747.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_38748_39143.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_39144_40499.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_40500_40763.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_40764_44723.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_44724_45107.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_45108_45431.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_45432_47111.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_47112_52883.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_52884_53819.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_53820_62555.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_62556_72959.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_72960_80147.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_80148_81623.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_81624_81671.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_81672_81863.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_81864_84959.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_84960_85247.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_85248_85331.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_85332_85379.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_85380_85751.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_85752_86843.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_86844_86903.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_86904_87059.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_87060_87131.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_87132_87287.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_87288_87419.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_87420_87887.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_87888_88199.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_88200_88271.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_88272_88787.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_88788_89003.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_89004_89051.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_89052_89171.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_89172_89627.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_89628_89783.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_89784_90419.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_90420_91571.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_91572_92027.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_92028_92339.png A_closer_look_into_VSTS_Build_and_Release_Management_Rene_van_Osnabrugge_92340_92545.png