Skip to content

Commit 6719689

Browse files
authored
Merge pull request #18 from tfsaggregator/rel-0.4
Rel 0.4
2 parents ec3335a + 721e649 commit 6719689

File tree

86 files changed

+2713
-592
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+2713
-592
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ ASALocalRun/
332332

333333
# MFractors (Xamarin productivity tool) working folder
334334
.mfractor/
335+
336+
## Specific to this repo
335337
secrets/
336338
src/aggregator-cli/FunctionRuntime.zip
337339
*.exe

README.md

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
11
# aggregator-cli
22

3-
![](https://tfsaggregator.visualstudio.com/_apis/public/build/definitions/1cca877b-3e26-4880-b5b8-79e4b10fbfb4/16/badge)
3+
[![Build status: master](https://dev.azure.com/TfsAggregator/Aggregator3/_apis/build/status/Aggregator3-CI?branchName=master)](https://dev.azure.com/TfsAggregator/Aggregator3/_build/latest?definitionId=16)
4+
[![Build status](https://dev.azure.com/TfsAggregator/Aggregator3/_apis/build/status/Aggregator3-CI)](https://dev.azure.com/TfsAggregator/Aggregator3/_build/latest?definitionId=16)
5+
46

57
This is the successor to TFS Aggregator.
68
The current Server Plugin version (2.x) will be maintained to support TFS.
79
The Web Service flavor will be discontinued in favor of this (its deployment and configuration was too complex for most users).
810

9-
The main scenario for Aggregator (3.x) is supporting VSTS and the cloud scenario. It will work for TFS as long as it is reachable from Internet.
11+
The main scenario for Aggregator (3.x) is supporting Azure DevOps and the cloud scenario. It will work for TFS as long as it is reachable from Internet.
1012

11-
> **This is an early version (alpha)**: we might change verbs and rule language before the final release!
13+
> **This is an early version (beta)**: we might change verbs and rule language before the final release!
14+
*Note*: The documentation is limited to this page and the content of the `doc` folder.
1215

1316
## Major features
1417

15-
- use of new REST API
18+
- use of new Azure DevOps REST API
1619
- simple deployment via CLI tool
17-
- similar model for Rules
20+
- Rule object model similar to v2
1821

1922
## Planned features
2023

2124
- Support for Deployment Slots for blue/green-style deployments
2225
- OAuth support to avoid maintain access tokens
23-
- Additional VSTS events
24-
- Additional VSTS objects
26+
- Additional Azure DevOps events
27+
- Additional Azure DevOps objects
2528

2629
## How it works
2730

2831
An Aggregator Instance is an Azure Function Application in its own Resource Group,
29-
sharing the same VSTS credential. You can have only one Application per Resource Group.
32+
sharing the same Azure DevOps credential. You can have only one Application per Resource Group.
3033
If the Resource Group does not exists, Aggregator will try to create it.
3134
*Note*: The Instance name must be **unique** amongst all Aggregator Instances in Azure!
3235

@@ -36,28 +39,28 @@ To work, it uses an Aggregator Runtime.
3639
Aggregator checks its latest GitHub Release to ensure that Aggregator Runtime is up-to-date before uploading the function.
3740
*Note*: We use [Azure Functions Runtime](https://docs.microsoft.com/en-us/azure/azure-functions/functions-versions) 2.0 for C# which is still in Preview.
3841

39-
An Aggregator Mapping is a VSTS Service Hook for a specific work item event that invokes an Aggregator Rule i.e. the Azure Function hosting the Rule code. VSTS saves the Azure Function Key in the Service Hook configuration.
42+
An Aggregator Mapping is a Azure DevOps Service Hook for a specific work item event that invokes an Aggregator Rule i.e. the Azure Function hosting the Rule code. Azure DevOps saves the Azure Function Key in the Service Hook configuration.
4043

41-
You can deploy the same Rule in many Instances or map the same VSTS event to many Rules: it is up how to organize.
44+
You can deploy the same Rule in many Instances or map the same Azure DevOps event to many Rules: it is up to you choosing the best way to organize.
4245

4346
## Authentication
4447

4548
You must instruct Aggregator which credential to use.
46-
To do this, run the `login.azure` and `login.vsts` commands.
49+
To do this, run the `login.azure` and `login.ado` commands.
4750

48-
To create the credentials, you need an Azure Service Principal and a VSTS Personal Access Token.
51+
To create the credentials, you need an Azure Service Principal and a Azure DevOps Personal Access Token.
4952

50-
These documents will guide you
53+
These documents will guide you in creating the credentials
5154
* [Use portal to create an Azure Active Directory application and service principal that can access resources](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal)
52-
* [Create personal access tokens to authenticate access](https://docs.microsoft.com/en-us/vsts/organizations/accounts/use-personal-access-tokens-to-authenticate?view=vsts#create-personal-access-tokens-to-authenticate-access).
55+
* [Create personal access tokens to authenticate access](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate).
5356

5457
Logon credentials are stored locally and expire after 2 hours.
5558

56-
The PAT is stored in the Azure Function settings: **whoever has access to the Resource Group can read it!**
59+
The PAT is also stored in the Azure Function settings: **whoever has access to the Resource Group can read it!**
5760

58-
The Service Principal must have Contributor permission to the Azure Subscription.
59-
In alternative, pre-create the `aggregator-` Resource Group in Azure and give the service account Contributor permission to the Resource Group.
60-
The `instance` parameter prefixes `aggregator-` to identify the Resource Group.
61+
The Service Principal must have Contributor permission to the Azure Subscription or, in alternative, pre-create the Resource Group in Azure and give the service account Contributor permission to the Resource Group.
62+
![Permission on existing Resource Group](doc/contributor-on-rg.png)
63+
If you go this route, remember add the `--resourceGroup` to all commands requiring an instance, otherwise the `instance` parameter adds an `aggregator-` prefixe to find the Resource Group.
6164

6265
## Usage
6366

@@ -71,24 +74,29 @@ To run Aggregator use
7174
Verb | Use
7275
--------------------|----------------------------------------
7376
logon.azure | Logon into Azure.
74-
logon.vsts | Logon into Visual Studio Team Services.
77+
logon.ado | Logon into Azure DevOps.
7578
list.instances | Lists Aggregator instances.
7679
install.instance | Creates a new Aggregator instance in Azure.
7780
uninstall.instance | Destroy an Aggregator instance in Azure.
81+
configure.instance | Configures an existing Aggregator instance.
7882
list.rules | List the rule in existing Aggregator instance in Azure.
7983
add.rule | Add a rule to existing Aggregator instance in Azure.
8084
remove.rule | Remove a rule from existing Aggregator instance in Azure.
81-
configure.rule | Change a rule configuration and code.
82-
list.mappings | Lists mappings from existing VSTS Projects to Aggregator Rules.
83-
map.rule | Maps an Aggregator Rule to existing VSTS Projects.
84-
unmap.rule | Unmaps an Aggregator Rule from a VSTS Project.
85+
configure.rule | Change a rule configuration.
86+
update.rule | Update a rule code and/or runtime.
87+
invoke.rule | Executes a rule locally or in an existing Aggregator instance.
88+
list.mappings | Lists mappings from existing Azure DevOps Projects to Aggregator Rules.
89+
map.rule | Maps an Aggregator Rule to existing Azure DevOps Projects.
90+
unmap.rule | Unmaps an Aggregator Rule from a Azure DevOps Project.
8591
help | Display more information on a specific command.
8692
version | Display version information.
8793

88-
## Examples
94+
You can see a few Command examples in [Sample Aggregator CLI usage](doc/command-examples.md), see also [Manual Tests](doc/test-matrix.md).
95+
96+
## Rule language
8997

90-
You can see a few Command examples in [Sample Aggregator CLI usage](doc/command-examples.md).
91-
You can see a few Rule examples in [Rule Examples](doc/rule-examples.md).
98+
See [Rule Language](doc/rule-language.md) for a list of objects and properties to use.
99+
For examples see [Rule Examples](doc/rule-examples.md).
92100

93101
## Troubleshooting
94102

doc/build-and-test.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Build
2+
Building locally requires
3+
- Visual Studio 2017 15.8.9
4+
- Azure Functions and Web Jobs Tools
5+
6+
# Debug
7+
8+
## Custom/development Aggregator runtime
9+
In Visual Studio, `src\aggregator-function\Directory.Build.targets` will automatically package and copy the runtime needed by CLI.
10+
You might have to change the version number in `src\aggregator-function\aggregator-manifest.ini` to force your local version.
11+
12+
You can also use the *Pack* right-click command on the `aggregator-function` project and make sure to copy the created zip into your CLI directory so it uploads the correct one when creating an instance.
13+
14+
## CLI
15+
Set `aggregator-cli` as Start-up project
16+
Use the Visual Studio Project properties to set the Command line arguments
17+
18+
## Runtime
19+
Set `aggregator-function` as Start-up project
20+
Use **Postman** or similar tool to send the request at http://localhost:7071/api/name_of_rule
21+
22+
# Integration tests
23+
`git update-index --assume-unchanged src/integrationtests-cli/logon-data.json` and edit the file content

doc/command-examples.md

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,60 @@ Remember that the Instance name must be unique in Azure.
55
```
66
# logon
77
logon.azure --subscription 9c********08 --client 5a********b6 --password P@assword1 --tenant 3c********1d
8-
logon.vsts --url https://someaccount.visualstudio.com --mode PAT --token 2**************************************q
8+
logon.ado --url https://someaccount.visualstudio.com --mode PAT --token 2**************************************q
99
1010
# create an Azure Function Application
1111
install.instance --verbose --name my1 --location westeurope
12+
install.instance --name my3 --resourceGroup myRG1 --location westeurope --requiredVersion latest
13+
# search instances in the Azure subscription
1214
list.instances
15+
# search instances in the Azure Resource Group
16+
list.instances --resourceGroup myRG1
1317
14-
# create three Azure Functions
18+
# create two Azure Functions
1519
add.rule --verbose --instance my1 --name test1 --file test\test1.rule
1620
add.rule --verbose --instance my1 --name test2 --file test\test2.rule
17-
add.rule --verbose --instance my1 --name test3 --file test\test3.rule
1821
list.rules --verbose --instance my1
1922
20-
# adds two Service Hook to VSTS, each invoking a different rule
23+
# create Azure Function in specified App and Resource Group
24+
add.rule --verbose --instance my3 --resourceGroup myRG1 --name test3 --file test\test3.rule
25+
26+
# adds two Service Hook to Azure DevOps, each invoking a different rule
2127
map.rule --verbose --project SampleProject --event workitem.created --instance my1 --rule test1
2228
map.rule --verbose --project SampleProject --event workitem.updated --instance my1 --rule test2
29+
map.rule --verbose --project SampleProject --event workitem.created --instance my3 --resourceGroup myRG1 --rule test3
30+
31+
2332
list.mappings --verbose --instance my1
33+
list.mappings --verbose --project SampleProject
34+
list.mappings --instance my1 --project SampleProject
2435
25-
# disable a rule
36+
# disable an existing rule
2637
configure.rule --verbose --instance my1 --name test1 --disable
2738
# re-enable a rule
2839
configure.rule --verbose --instance my1 --name test1 --enable
29-
# update the code of a rule
30-
configure.rule --verbose --instance my1 --name test --update test.rule
40+
# update the code and runtime of a rule
41+
update.rule --verbose --instance my1 --name test1 --file test1.rule --requiredVersion 0.4.0
42+
update.rule --verbose --instance my3 --resourceGroup myRG1 --name test3 --file test\test3.rule
3143
32-
# updates the VSTS credential stored by the rules
33-
configure.instance --authentication
44+
# updates the Azure DevOps credential stored in Azure Function and used by rules to connect back
45+
configure.instance --name my1 --location westeurope --authentication
46+
configure.instance --name my3 --resourceGroup myRG1 --location westeurope --authentication
3447
35-
# remove a Service Hook from VSTS
48+
# remove a Service Hook from Azure DevOps
3649
unmap.rule --verbose --event workitem.created --instance my1 --rule test1
50+
unmap.rule --verbose --event workitem.updated --project SampleProject --instance my1 --rule test2
51+
unmap.rule --verbose --project SampleProject --event workitem.created --instance my3 --resourceGroup myRG1 --rule test3
3752
38-
# deletes two Azure Functions
53+
# deletes an Azure Function and all Service Hooks referring to it
3954
remove.rule --verbose --instance my1 --name test1
40-
remove.rule --verbose --instance my1 --name test2
55+
remove.rule --verbose --instance my3 --resourceGroup myRG1 --name test3
56+
57+
# delete the Azure Function Application leaving the Service Hooks in place
58+
uninstall.instance --name my1 --location westeurope --dont-remove-mappings
59+
# delete the Azure Function Application and any Service Hooks referring to it
60+
uninstall.instance --verbose --name my3 --resourceGroup myRG1 --location westeurope
4161
42-
# delete the Azure Function Application
43-
uninstall.instance --verbose --name my1 --location westeurope
62+
# run rule locally, no change is sent to Azure DevOps
63+
invoke.rule --dryrun --project SampleProject --event workitem.created --workItemId 14 --local --source test\test2.rule
4464
```

doc/contributor-on-rg.png

17.4 KB
Loading

doc/rule-examples.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ $"Hello { self.WorkItemType } #{ self.Id } - { self.Title }!"
1212

1313
This is more similar to classic TFS Aggregator.
1414
It move a parent work item to Closed state, if all children are closed.
15-
The major difference is the navigation: `Parent` and `Children` properties do not returns work items but relation. You have to explicitly query VSTS to retrieve the referenced work items.
15+
The major difference is the navigation: `Parent` and `Children` properties do not returns work items but relation. You have to explicitly query Azure DevOps to retrieve the referenced work items.
1616

1717
```
1818
string message = "";
19-
if (self.Parent != null)
19+
var parent = self.Parent;
20+
if (parent != null)
2021
{
21-
var parent = store.GetWorkItem(self.Parent);
22-
var children = store.GetWorkItems(parent.Children);
22+
var children = parent.Children;
2323
if (children.All(c => c.State == "Closed"))
2424
{
2525
parent.State = "Closed";
@@ -41,3 +41,13 @@ return message;
4141
```
4242
return self.PreviousRevision.PreviousRevision.Description;
4343
```
44+
45+
# Create new Work Item
46+
```
47+
var parent = self;
48+
var newChild = store.NewWorkItem("Task");
49+
newChild.Title = "Brand new child";
50+
parent.Relations.AddChild(newChild);
51+
52+
return parent.Title;
53+
```

doc/rule-language.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Directives
2+
3+
`.lang=C#`
4+
`.language=Csharp`
5+
6+
7+
8+
# WorkItem Object
9+
10+
## Revisions
11+
Navigate to previous versions of the work item.
12+
`WorkItem PreviousRevision`
13+
`IEnumerable<WorkItem> Revisions`
14+
15+
## Relations
16+
Navigate to related work items.
17+
`IEnumerable<WorkItemRelation> RelationLinks`
18+
`WorkItemRelationCollection Relations`
19+
`IEnumerable<WorkItemRelation> ChildrenLinks`
20+
`IEnumerable<WorkItem> Children`
21+
`WorkItemRelation ParentLink`
22+
`WorkItem Parent`
23+
24+
## Links
25+
Navigate links to non-workitem objects.
26+
`IEnumerable<WorkItemRelation> RelatedLinks`
27+
`IEnumerable<WorkItemRelation> Hyperlinks`
28+
`int ExternalLinkCount`
29+
`int HyperLinkCount`
30+
`int RelatedLinkCount`
31+
32+
## Fields
33+
Data fields of the work item.
34+
`WorkItemId<int> Id` Read-only.
35+
`int Rev` Read-only.
36+
`string Url` Read-only.
37+
`string WorkItemType` Read-only.
38+
`string State`
39+
`int AreaId`
40+
`string AreaPath`
41+
`IdentityRef AssignedTo`
42+
`IdentityRef AuthorizedAs`
43+
`IdentityRef ChangedBy`
44+
`DateTime? ChangedDate`
45+
`IdentityRef CreatedBy`
46+
`DateTime? CreatedDate`
47+
`string Description`
48+
`string History`
49+
`int IterationId`
50+
`string IterationPath`
51+
`string Reason`
52+
`DateTime? RevisedDate`
53+
`DateTime? AuthorizedDate`
54+
`string TeamProject`
55+
`string Tags`
56+
`string Title`
57+
`double Watermark` Read-only.
58+
`bool IsDeleted` Read-only.
59+
`bool IsReadOnly` Read-only, returns `true` if work item cannot be modified.
60+
`bool IsNew` Read-only.
61+
`bool IsDirty` Read-only, returns `true` if work item changed after retrieval.
62+
`object this[string field]` access to non-core fields.
63+
64+
## Attachments
65+
`int AttachedFileCount`
66+
67+
68+
69+
# WorkItemStore Object
70+
Retrival, creation and removal of work items.
71+
72+
`WorkItem GetWorkItem(int id)`
73+
`WorkItem GetWorkItem(WorkItemRelation item)`
74+
75+
`IList<WorkItem> GetWorkItems(IEnumerable<int> ids)`
76+
`IList<WorkItem> GetWorkItems(IEnumerable<WorkItemRelation> collection)`
77+
78+
`WorkItemWrapper NewWorkItem(string workItemType)`
79+
80+
81+
82+
# WorkItemRelationCollection
83+
Navigate and modify related objects.
84+
85+
`IEnumerator<WorkItemRelation> GetEnumerator()`
86+
`Add(WorkItemRelation item)`
87+
`AddChild(WorkItemWrapper child)`
88+
`AddParent(WorkItemWrapper parent)`
89+
`AddLink(string type, string url, string comment)`
90+
`AddHyperlink(string url, string comment = null)`
91+
`AddRelatedLink(WorkItem item, string comment = null)`
92+
`AddRelatedLink(string url, string comment = null)`
93+
`Clear()`
94+
`bool Contains(WorkItemRelation item)`
95+
`bool Remove(WorkItemRelation item)`
96+
`int Count`
97+
`bool IsReadOnly`
98+
99+
100+
101+
# WorkItemRelation
102+
103+
`string Title`
104+
`string Rel`
105+
`string Url`
106+
`IDictionary<string, object> Attributes`
107+
108+
109+
110+
# IdentityRef
111+
Represents a User identity.
112+
113+
`string DirectoryAlias`
114+
`string DisplayName`
115+
`string Id`
116+
`string ImageUrl`
117+
`bool Inactive`
118+
`bool IsAadIdentity`
119+
`bool IsContainer`
120+
`string ProfileUrl`
121+
`string UniqueName`
122+
`string Url`

doc/service-principal.png

40.3 KB
Loading

0 commit comments

Comments
 (0)