Azure DevOps has always provided the facility of defining Scheduled pipelines using UI Editor. With the push of Sprint 137, this functionality is now moved to the Cron Syntax. (And not Cron-like Syntax :)) Not only the cron syntax is more prominent in the Software world, it also provides more granularity than the UI editor. Also, you can define multiple schedules simultaneously for a single pipelines, allowing you even more flexibility. Not to mention, you can also manage and track build schedules as part of the code. In this blog post, we’ll learn about the same.
Pipeline syntax to define cron schedule
We can define cron schedules using below syntax:
|– cron: string # cron syntax defining a schedule|
|displayName: string # friendly name given to a specific schedule|
|# include is calculated first followed by exclude|
|# there is no implicit include|
|include: [ string ] # which branches the schedule applies to|
|exclude: [ string ] # which branches to exclude from the schedule|
|always: boolean # whether to always run the pipeline or only if there have been source code changes since the last run. The default is false.|
Comments are pretty descriptive in nature, so I’ll leave it there only. Note that the time zone is always UTC for the defined schedule. So you’ll need to adjust for the difference between your time zone and UTC. Also, the UTC time zones in YAML scheduled triggers do not account for daylight savings time.
For example, let’s say we want to build daily midnight time in India which is UTC +0530 Hrs. Then we need to run the build at 1730 HRS in UTC for which cron syntax would be:
17 30 * * *. Here, Days and Months and Days of the weeks are defined using wildcard (*), since we need it to run on all days.
Defining Cron Schedule in Practice
Below azure pipeline code defines the cron-schedules for building our .NET Core application:
|# Sample pipeline code to demonstrate scheduling using cron syntax|
|name: 'Hosted Ubuntu 1604'|
|– cron: "0 * * * *"|
|displayName: "hourly build"|
|– cron: "0 0 * * *"|
|displayName: "daily midnight build"|
|– script: ||
|dotnet build –configuration $(buildConfiguration)|
|dotnet test dotnetcore-tests –configuration $(buildConfiguration) –logger trx|
|dotnet publish –configuration $(buildConfiguration) –output out|
We have defined separate schedule for the ‘cron-schedule’ branch and set it to hourly builds. Since we have included one branch, all other branches are auto excluded.
Similarly, we have defined midnight builds for
features/* branches but excluding branches falling under
Once we have defined schedules in the YAML pipeline, we need to commit the code and Azure DevOps will pick up the same. After this, we can see the builds getting triggered at schedules defined.
Building Cron Syntax
Each cron syntax consists of 5 values separated by Space character:
mm HH DD MM DW \ \ \ \ \__ Days of week \ \ \ \____ Months \ \ \______ Days \ \________ Hours \__________ Minutes
We can use following table to create understand syntax:
|mm||Minutes||0 to 59|
|DD||Hours||0 to 23|
|MM||Months||1 through 12, full English names, first three letters of English names|
|DW||Days of the Week||0 through 6 (starting with Sunday), full English names, first three letters of English names|
Values can be provided in following formats:
|Wildcard||*||Matches all values for this field|
|Single value||5||Specifies a single value for this field|
|Comma delimited||3,5,6||Specifies multiple values for this field. Multiple formats can be combined, like 1,3-6|
|Ranges||1-3||The inclusive range of values for this field|
|Intervals||*/4 or 1-5/2||Intervals to match for this field, such as every 4th value or the range 1-5 with a step interval of 2|
Summary and Notes
Ability to define build schedules using cron syntax as part of the yaml code allows more granularity and flexibility. It allows to also track and manage schedules as part of the source code.
A copy of the source code used in this blog post can be found at here on GitHub under branches blog/8402 and master branch.
If you are not able to see the source code when viewing in-app browsers, open this blog post in a proper browser on your device.