This tool gets the current policies for projects, repositories and branches, or applies policy settings over a team project collection based on a JSON configuration file.
Stable | Pre-release | |
---|---|---|
GitHub Release | - | |
Chocolatey |
The tool is targeted to .Net 7.0 / meaning, it can be used besides windows machines also on linux, macs, etc. The tool is wrapped in a Chocolatey package, so it can be easily installed onto a windows 10 machine, where the package builds an executable itself, and installs it to the client machine. Nevertheless, the tool can be targeted onto any runtime. See runtime catalog here
choco install azure-devops-policy-configurator
dotnet publish -c Release -r win10-x64
dotnet publish -c Release -r ubuntu.16.10-x64
dotnet publish -c Release -r osx.10.12-x64
AzureDevOpsPolicyConfigurator generate
command generates JSON files from the current policy
structure. The tool iterates through every Team Project, gets every policy set groups them by
repository and saves in the policies.json
file. In the main directory, every project is saved
to the projects.json
file, and the tool also gets every type available in the current Team
Project, it stores them into the types.json
file in each project directory.
AzureDevOpsPolicyConfigurator generate --auth ntlm --collectionurl https://tfs.yourserver.ch/DefaultCollection
Option | Description |
---|---|
--collectionUrl or -c |
The Team Collection URL, e.g.: tfs.yourserver.ch/DefaultCollection |
--auth or -a |
The authentication method, option values: ntlm , oauth , basic , azureactivedirectory |
--user or -u |
The user for authentication (optional for PAT authentication, or for ntlm authentication with current user) |
--password or -p |
The password, PAT or token for the authentication (optional for ntlm authentication with current user) |
--verbosity or -v |
Sets the log4net root level, option values: info , debug , warn , error (optional, default is info ) |
--destination or -d |
optional, default value is .\Project |
AzureDevOpsPolicyConfigurator whatif
and AzureDevOpsPolicyConfigurator execute
command executes
a strategy stored in an input JSON file
AzureDevOpsPolicyConfigurator whatif -a ntlm -c https://tfs.yourserver.ch/DefaultCollection -i Sample\\testfile.json
AzureDevOpsPolicyConfigurator execute -a ntlm -c https://tfs.yourserver.ch/DefaultCollection -i Sample\\testfile.json
Option | Description |
---|---|
--collectionUrl or -c |
The Team Collection URL, e.g.: tfs.yourserver.ch/DefaultCollection |
--auth or -a |
The authentication method, option values: ntlm , oauth , basic , azureactivedirectory |
--user or -u |
The user for authentication (optional for PAT authentication, or for ntlm authentication with current user) |
--password or -p |
The password or PAT for the authentication (optional for ntlm authentication with current user) |
--verbosity or -v |
Sets the log4net root level, option values: info , debug , warn , error (optional, default is info ) |
--in or -i |
the input JSON settings file (Multiple files can be specified with the delimiter: ; . These files will be merged.) |
Policy definitions are stored in the input file, which can be defined globally, global for a project,
global for a repository, global for specific branches, global for specific branches in a project,
and for specific branches in a repository.
It is possible to ignore policies during the simulation or execution run, if some of them are set
or handled manually on the UI. Use the ignoreTypes
section for that.
For project, repository and type definitions, both ids and entity names can be used to ease the
setting of the rules.
Azure DevOps stores the policies only on project level, nevertheless the tool gathers every definition and takes and sets the most specific for a repository and type, meaning, first a branch and repository specific, then, if that does not exist, a branch specific global policy. It applies then the non-branch specific policies, the order is repository, then project specific, then global. The tool goes through each and every repository in every project in the specified team collection and updates it (if the rule is different, otherwise the rule won't be touched), creates the rule, or deletes it, if it's not defined int the JSON file!
Note: Do not define the
isEnabled
andisDeleted
flags, these will be automatically set by the tool, and would lead to endless updates due to permanent difference!
There are types which can be used more then once on a repository (like Status
), and defers only in
some sort of subtype. There is a possibility to specify these subtypes with the subTypePropertyName
and subTypePropertyValue
properties in the definition, besides this, these policy definitions
can also be set hierarchically.
Note: At creation or the scope property in the definition, if defined will be removed and set by the tool, also, if the subType feature is used, this property will be overriden by the tool. For comparison these properties are ignored.
The tool has been built defensive, meaning, deletion is not allowed by default. If you want to
enable this functionality, set the allowDeletion
property to true
. (The property is optional,
default is false
)
If the tool should only touch specific project(s) or repository(ies), the restriction should be
added to the applyTo
section of the yaml file. (The section and its properties is optional, can
be removed, if not needed.)
{
"allowDeletion": false,
"ignoreTypes": [
"Status"
],
"applyTo": {
"projects": [],
"repositories": []
},
"policies": [
{
"type": "Minimum number of reviewers",
"project": "",
"branch": "",
"repository": "",
"isBlocking": true,
"settings": {
"minimumApproverCount": 2,
"creatorVoteCounts": false,
"allowDownvotes": false,
"resetOnSourcePush": false
}
},
{
"type": "Minimum number of reviewers",
"project": "MyProject",
"branch": "",
"repository": "",
"isBlocking": true,
"settings": {
"minimumApproverCount": 2,
"creatorVoteCounts": false,
"allowDownvotes": false,
"resetOnSourcePush": false
}
}
]
}
{
"type": "Minimum number of reviewers",
"project": "",
"branch": "",
"repository": "",
"isBlocking": true,
"settings": {
"minimumApproverCount": 2,
"creatorVoteCounts": false,
"allowDownvotes": false,
"resetOnSourcePush": false
}
}
{
"type": "Minimum number of reviewers",
"project": "MyProject",
"branch": "",
"repository": "",
"isBlocking": true,
"settings": {
"minimumApproverCount": 2,
"creatorVoteCounts": false,
"allowDownvotes": false,
"resetOnSourcePush": false
}
}
{
"type": "Minimum number of reviewers",
"project": "",
"branch": "",
"repository": "MyRepository",
"isBlocking": true,
"settings": {
"minimumApproverCount": 2,
"creatorVoteCounts": false,
"allowDownvotes": false,
"resetOnSourcePush": false
}
}
{
"type": "Require a merge strategy",
"project": "",
"branch": "release/*",
"repository": "",
"isBlocking": true,
"settings": {
"useSquashMerge": false
}
}
{
"type": "Require a merge strategy",
"project": "",
"branch": "master",
"matchKind": "exact",
"repository": "",
"isBlocking": true,
"settings": {
"useSquashMerge": false
}
}
{
"type": "Require a merge strategy",
"project": "",
"branches": ["master", "release/*"],
"matchKind": "exact",
"repository": "",
"isBlocking": true,
"settings": {
"useSquashMerge": false
}
}
{
"type": "Require a merge strategy",
"project": "MyProject",
"branch": "feature/*",
"repository": "MyRepository",
"isBlocking": true,
"settings": {
"useSquashMerge": false
}
}
For every feature branch under the "MyRepository" and "MyRepository2" repositories in the "MyProject" project
{
"type": "Require a merge strategy",
"project": "MyProject",
"branch": "feature/*",
"repositories": ["MyRepository", "MyRepository2"],
"isBlocking": true,
"settings": {
"useSquashMerge": false
}
}
For the master and every feature branch under the "MyRepository" and "MyRepository2" repositories in the "MyProject" project
{
"type": "Require a merge strategy",
"project": "MyProject",
"branches": [ "master", "feature/*" ],
"repositories": ["MyRepository", "MyRepository2"],
"isBlocking": true,
"settings": {
"useSquashMerge": false
}
}
{
"type": "Status",
"subTypePropertyName": "statusName",
"subTypePropertyValue": "work-in-progress",
"isBlocking": true,
"settings": {
"statusGenre": "MyGenre",
"authorId": "88148664-b0c6-4fab-bbd8-aae5d3e7d233",
"invalidateOnSourceUpdate": false,
"filenamePatterns": []
}
},
{
"type": "Status",
"subTypePropertyName": "statusName",
"subTypePropertyValue": "pullrequest-title",
"isBlocking": true,
"settings": {
"statusName": "pullrequest-title",
"statusGenre": "MyGenre",
"authorId": "88148664-b0c6-4fab-bbd8-aae5d3e7d233",
"invalidateOnSourceUpdate": false,
"filenamePatterns": []
}
}