In my previous posts, I’ve shown people how to use VSTS (formerly known as VSO) to trigger continuous testing using builds and release management. I was able to utilize new reporting capabilities in build, particularly, test reports. I created reports that shows pass/fail trends for tests in my build definitions.
There are still limitations (or in this case features I wish Microsoft would consider such as customizing test reports from builds as well as showing pass/fail trends past 10 builds). My biggest disappointment thus far is “NOT” able to schedule build (with tests) using re-occurring pattern/s. As of writing this post, you can schedule builds in VSTS however, you have to “manually” keep adding scheduled times.
Imagine a scenario where you need to run a build every hour (or half hour), you have to manually add new times every hour, in this case, 24 times. Very inconvenient.
Fortunately, VSTS has public API’s that allows us to access build execution and trigger. With the public API’s I was able to write a very simple console app and use Windows’ built in “Task Scheduler” functionality. One would say, why not create a windows services? Yes, that’s option but I would make a point back to say: “Why develop a windows service further complicating the process where Windows has ‘Task Scheduler’ that’s been tested and used more broadly?”
Below is the code:
NOTE: You need to refer to the following Nuget Packages:
- Microsoft.TeamFoundationServer.ExtendedClient
- Microsoft.TeamFoundationServer.Client
- Microsoft.VisualStudio.Services.Client
- Microsoft.VisualStudio.Services.InteractiveClient
static class Program { static void Main(string[] args) { var buildoutputmodel = SetupBuildOutputModel(); var vssconnection = new VssConnection( new Uri(buildoutputmodel.VsoUrl), new VssBasicCredential(buildoutputmodel.UserName, buildoutputmodel.Password) ); var buildHttpClient = vssconnection.GetClient<BuildHttpClient>(); //Below is my implementation of triggering multiple builds. I simply used the app.config to specify the build's ID, split each entry and validate. ConfigurationManager.AppSettings["builddefinitionids"].Split(',').ToList().ForEach( buildid => { string stringoutput; try { var id = buildid.ValidateBuildId(); DefinitionReference definitionReference = new DefinitionReference { Id = id, Project = new TeamProjectReference { Name = buildoutputmodel.TeamProjectName } }; var build = new Build { Definition = definitionReference }; //This is where you trigger the build var buildnumber = buildHttpClient.QueueBuildAsync(build, buildoutputmodel.TeamProjectName).Result; stringoutput = $"Build Triggered... \nBuild Number: {buildnumber} \nBuild Definition ID: {definitionReference.Id} \nTeam Project: {definitionReference.Project.Name}\n"; Console.WriteLine(stringoutput); AsLogger.Info(stringoutput); } catch (Exception ex) { stringoutput = $"Exception Occurred: \n{ex.Message} \n{ex.InnerException}\n"; Console.WriteLine(stringoutput); AsLogger.Error(stringoutput); } }); } private static BuildOutputModel SetupBuildOutputModel() { return new BuildOutputModel { UserName = ConfigurationManager.AppSettings["username"], Password = ConfigurationManager.AppSettings["password"], VsoUrl = ConfigurationManager.AppSettings["vsourl"], TeamProjectName = ConfigurationManager.AppSettings["teamproject"], BuilDefinitionName = ConfigurationManager.AppSettings["builddefinition"], GitRepo = ConfigurationManager.AppSettings["gitrepo"] }; } }
Once you compile the code (.exe), simply create a scheduled task using Windows’ Task Scheduler:
Then the execution: