예제 #1
0
        private async Task <string> ExecAsyncImpl(IRule rule, WorkItemEventContext eventContext, VssCredentials clientCredentials, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // TODO improve from https://github.com/Microsoft/vsts-work-item-migrator
            using var devops = new VssConnection(eventContext.CollectionUri, clientCredentials);
            try
            {
                await devops.ConnectAsync(cancellationToken);

                logger.WriteInfo($"Connected to Azure DevOps");
            }
            catch (System.Exception ex)
            {
                logger.WriteError(ex.Message);
                if (ex.InnerException != null)
                {
                    logger.WriteError(ex.InnerException.Message);
                }
                throw ex;
            }
            using var clientsContext = new AzureDevOpsClientsContext(devops);
            var engine = new RuleEngine(logger, configuration.SaveMode, configuration.DryRun);

            var ruleResult = await engine.RunAsync(rule, eventContext.ProjectId, eventContext.WorkItemPayload, eventContext.EventType, clientsContext, cancellationToken);

            logger.WriteInfo(ruleResult);
            return(ruleResult);
        }
예제 #2
0
        public async Task <string> ExecuteAsync(IRule rule, WorkItemEventContext eventContext, CancellationToken cancellationToken)
        {
            logger.WriteVerbose($"Connecting to Azure DevOps using {configuration.DevOpsTokenType}...");
            var clientCredentials = default(VssCredentials);

            if (configuration.DevOpsTokenType == DevOpsTokenType.PAT)
            {
                clientCredentials = new VssBasicCredential(configuration.DevOpsTokenType.ToString(), configuration.DevOpsToken);
            }
            else
            {
                logger.WriteError($"Azure DevOps Token type {configuration.DevOpsTokenType} not supported!");
                throw new ArgumentOutOfRangeException(nameof(configuration.DevOpsTokenType));
            }

            cancellationToken.ThrowIfCancellationRequested();

            // TODO improve from https://github.com/Microsoft/vsts-work-item-migrator
            using (var devops = new VssConnection(eventContext.CollectionUri, clientCredentials))
            {
                await devops.ConnectAsync(cancellationToken);

                logger.WriteInfo($"Connected to Azure DevOps");
                using (var clientsContext = new AzureDevOpsClientsContext(devops))
                {
                    var engine = new RuleEngine(logger, configuration.SaveMode, configuration.DryRun);

                    var ruleResult = await engine.RunAsync(rule, eventContext.ProjectId, eventContext.WorkItemPayload, clientsContext, cancellationToken);

                    logger.WriteInfo(ruleResult);
                    return(ruleResult);
                }
            }
        }
예제 #3
0
        private async Task <string> ExecAsyncImpl(IRule rule, WorkItemEventContext eventContext, VssCredentials clientCredentials, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var devops = await ConnectToAzureDevOpsAsync(eventContext, clientCredentials, cancellationToken);

            using var clientsContext = new AzureDevOpsClientsContext(devops);
            var engine = new RuleEngine(logger, configuration.SaveMode, configuration.DryRun);

            var ruleResult = await engine.RunAsync(rule, eventContext.ProjectId, eventContext.WorkItemPayload, eventContext.EventType, clientsContext, cancellationToken);

            logger.WriteInfo(ruleResult);
            return(ruleResult);
        }
예제 #4
0
        public async Task <string> ExecuteAsync(Guid projectId, WorkItemData workItemPayload, IClientsContext clients, CancellationToken cancellationToken)
        {
            if (State == EngineState.Error)
            {
                return(string.Empty);
            }

            var workItem    = workItemPayload.WorkItem;
            var context     = new EngineContext(clients, projectId, workItem.GetTeamProject(), logger);
            var store       = new WorkItemStore(context, workItem);
            var self        = store.GetWorkItem(workItem.Id.Value);
            var selfChanges = new WorkItemUpdateWrapper(workItemPayload.WorkItemUpdate);

            logger.WriteInfo($"Initial WorkItem {self.Id} retrieved from {clients.WitClient.BaseAddress}");

            var globals = new Globals
            {
                self        = self,
                selfChanges = selfChanges,
                store       = store,
                logger      = logger
            };

            logger.WriteInfo($"Executing Rule...");
            var result = await roslynScript.RunAsync(globals, cancellationToken);

            if (result.Exception != null)
            {
                logger.WriteError($"Rule failed with {result.Exception}");
                State = EngineState.Error;
            }
            else
            {
                logger.WriteInfo($"Rule succeeded with {result.ReturnValue ?? "no return value"}");
                State = EngineState.Success;
            }

            logger.WriteVerbose($"Post-execution, save any change (mode {saveMode})...");
            var saveRes = await store.SaveChanges(saveMode, !DryRun, cancellationToken);

            if (saveRes.created + saveRes.updated > 0)
            {
                logger.WriteInfo($"Changes saved to Azure DevOps (mode {saveMode}): {saveRes.created} created, {saveRes.updated} updated.");
            }
            else
            {
                logger.WriteInfo($"No changes saved to Azure DevOps.");
            }

            return(result.ReturnValue);
        }
예제 #5
0
        public async Task <string> ExecuteAsync(string collectionUrl, Guid projectId, string projectName, string personalAccessToken, int workItemId, WorkItemTrackingHttpClientBase witClient, CancellationToken cancellationToken)
        {
            if (State == EngineState.Error)
            {
                return(string.Empty);
            }

            var context = new EngineContext(witClient, projectId, projectName, personalAccessToken, logger);
            var store   = new WorkItemStore(context);
            var self    = store.GetWorkItem(workItemId);

            logger.WriteInfo($"Initial WorkItem {workItemId} retrieved from {collectionUrl}");

            var globals = new Globals
            {
                self   = self,
                store  = store,
                logger = logger
            };

            logger.WriteInfo($"Executing Rule...");
            var result = await roslynScript.RunAsync(globals, cancellationToken);

            if (result.Exception != null)
            {
                logger.WriteError($"Rule failed with {result.Exception}");
                State = EngineState.Error;
            }
            else
            {
                logger.WriteInfo($"Rule succeeded with {result.ReturnValue ?? "no return value"}");
                State = EngineState.Success;
            }

            logger.WriteVerbose($"Post-execution, save any change (mode {saveMode})...");
            var saveRes = await store.SaveChanges(saveMode, !DryRun, cancellationToken);

            if (saveRes.created + saveRes.updated > 0)
            {
                logger.WriteInfo($"Changes saved to Azure DevOps (mode {saveMode}): {saveRes.created} created, {saveRes.updated} updated.");
            }
            else
            {
                logger.WriteInfo($"No changes saved to Azure DevOps.");
            }

            return(result.ReturnValue);
        }
예제 #6
0
        internal async Task <string> ExecuteAsync(dynamic data, CancellationToken cancellationToken)
        {
            string collectionUrl = data.resourceContainers.collection.baseUrl;
            string eventType     = data.eventType;
            int    workItemId    = (eventType != "workitem.updated")
                ? data.resource.id
                : data.resource.workItemId;
            Guid   teamProjectId   = data.resourceContainers.project.id;
            string teamProjectName = (eventType != "workitem.updated")
                ? data.resource.fields["System.TeamProject"]
                : data.resource.revision.fields["System.TeamProject"];

            logger.WriteVerbose($"Connecting to Azure DevOps using {configuration.DevOpsTokenType}...");
            var clientCredentials = default(VssCredentials);

            if (configuration.DevOpsTokenType == DevOpsTokenType.PAT)
            {
                clientCredentials = new VssBasicCredential(configuration.DevOpsTokenType.ToString(), configuration.DevOpsToken);
            }
            else
            {
                logger.WriteError($"Azure DevOps Token type {configuration.DevOpsTokenType} not supported!");
                throw new ArgumentOutOfRangeException(nameof(configuration.DevOpsTokenType));
            }

            cancellationToken.ThrowIfCancellationRequested();

            // TODO improve from https://github.com/Microsoft/vsts-work-item-migrator
            using (var devops = new VssConnection(new Uri(collectionUrl), clientCredentials))
            {
                await devops.ConnectAsync(cancellationToken);

                logger.WriteInfo($"Connected to Azure DevOps");
                using (var witClient = devops.GetClient <WorkItemTrackingHttpClient>())
                {
                    string ruleFilePath = Path.Combine(functionDirectory, $"{ruleName}.rule");
                    if (!File.Exists(ruleFilePath))
                    {
                        logger.WriteError($"Rule code not found at {ruleFilePath}");
                        return("Rule file not found!");
                    }

                    logger.WriteVerbose($"Rule code found at {ruleFilePath}");
                    string[] ruleCode;
                    using (var fileStream = File.OpenRead(ruleFilePath))
                    {
                        var reader = new StreamReader(fileStream);
                        ruleCode = await ReadAllLinesAsync(reader);
                    }

                    var engine = new Engine.RuleEngine(logger, ruleCode, configuration.SaveMode, configuration.DryRun);

                    return(await engine.ExecuteAsync(teamProjectId, teamProjectName, workItemId, witClient, cancellationToken));
                }
            }
        }
예제 #7
0
        internal async Task <string> Execute(dynamic data)
        {
            string collectionUrl = data.resourceContainers.collection.baseUrl;
            string eventType     = data.eventType;
            int    workItemId    = (eventType != "workitem.updated")
                ? data.resource.id
                : data.resource.workItemId;
            Guid   teamProjectId   = data.resourceContainers.project.id;
            string teamProjectName = (eventType != "workitem.updated")
                ? data.resource.fields["System.TeamProject"]
                : data.resource.revision.fields["System.TeamProject"];

            logger.WriteVerbose($"Connecting to Azure DevOps using {configuration.DevOpsTokenType}...");
            var clientCredentials = default(VssCredentials);

            if (configuration.DevOpsTokenType == DevOpsTokenType.PAT)
            {
                clientCredentials = new VssBasicCredential(configuration.DevOpsTokenType.ToString(), configuration.DevOpsToken);
            }
            else
            {
                logger.WriteError($"Azure DevOps Token type {configuration.DevOpsTokenType} not supported!");
                throw new ArgumentOutOfRangeException(nameof(configuration.DevOpsTokenType));
            }

            using (var devops = new VssConnection(new Uri(collectionUrl), clientCredentials))
            {
                await devops.ConnectAsync();

                logger.WriteInfo($"Connected to Azure DevOps");
                using (var witClient = devops.GetClient <WorkItemTrackingHttpClient>())
                {
                    string ruleFilePath = Path.Combine(functionDirectory, $"{ruleName}.rule");
                    if (!File.Exists(ruleFilePath))
                    {
                        logger.WriteError($"Rule code not found at {ruleFilePath}");
                        return("Rule file not found!");
                    }

                    logger.WriteVerbose($"Rule code found at {ruleFilePath}");
                    string[] ruleCode = File.ReadAllLines(ruleFilePath);

                    var engine = new Engine.RuleEngine(logger, ruleCode, configuration.SaveMode);

                    return(await engine.ExecuteAsync(collectionUrl, teamProjectId, teamProjectName, configuration.DevOpsToken, workItemId, witClient));
                }
            }
        }
예제 #8
0
        internal async Task <string> ExecuteAsync(WorkItemEventContext eventContext, CancellationToken cancellationToken)
        {
            logger.WriteVerbose($"Connecting to Azure DevOps using {configuration.DevOpsTokenType}...");
            var clientCredentials = default(VssCredentials);

            if (configuration.DevOpsTokenType == DevOpsTokenType.PAT)
            {
                clientCredentials = new VssBasicCredential(configuration.DevOpsTokenType.ToString(), configuration.DevOpsToken);
            }
            else
            {
                logger.WriteError($"Azure DevOps Token type {configuration.DevOpsTokenType} not supported!");
                throw new ArgumentOutOfRangeException(nameof(configuration.DevOpsTokenType));
            }

            cancellationToken.ThrowIfCancellationRequested();

            // TODO improve from https://github.com/Microsoft/vsts-work-item-migrator
            using (var devops = new VssConnection(eventContext.CollectionUri, clientCredentials))
            {
                await devops.ConnectAsync(cancellationToken);

                logger.WriteInfo($"Connected to Azure DevOps");
                using (var clientsContext = new AzureDevOpsClientsContext(devops))
                {
                    string ruleFilePath = Path.Combine(functionDirectory, $"{ruleName}.rule");
                    if (!File.Exists(ruleFilePath))
                    {
                        logger.WriteError($"Rule code not found at {ruleFilePath}");
                        return("Rule file not found!");
                    }

                    logger.WriteVerbose($"Rule code found at {ruleFilePath}");
                    string[] ruleCode;
                    using (var fileStream = File.OpenRead(ruleFilePath))
                    {
                        var reader = new StreamReader(fileStream);
                        ruleCode = await ReadAllLinesAsync(reader);
                    }

                    var engine = new Engine.RuleEngine(logger, ruleCode, configuration.SaveMode, configuration.DryRun);

                    return(await engine.ExecuteAsync(eventContext.ProjectId, eventContext.WorkItemPayload, clientsContext, cancellationToken));
                }
            }
        }
예제 #9
0
        protected RuleExecutionContext CreateRuleExecutionContext(Guid projectId, WorkItemData workItemPayload, IClientsContext clients)
        {
            var workItem    = workItemPayload.WorkItem;
            var context     = new EngineContext(clients, projectId, workItem.GetTeamProject(), logger);
            var store       = new WorkItemStore(context, workItem);
            var self        = store.GetWorkItem(workItem.Id.Value);
            var selfChanges = new WorkItemUpdateWrapper(workItemPayload.WorkItemUpdate);

            logger.WriteInfo($"Initial WorkItem {self.Id} retrieved from {clients.WitClient.BaseAddress}");

            var globals = new RuleExecutionContext
            {
                self        = self,
                selfChanges = selfChanges,
                store       = store,
                logger      = logger
            };

            return(globals);
        }
예제 #10
0
        /// <inheritdoc />
        public async Task <IRuleResult> ApplyAsync(RuleExecutionContext executionContext, CancellationToken cancellationToken)
        {
            var result = await _roslynScript.RunAsync(executionContext, cancellationToken);

            if (result.Exception != null)
            {
                _logger.WriteError($"Rule failed with {result.Exception}");
                return(new RuleResult()
                {
                    Outcome = RuleExecutionOutcome.Error,
                    Value = result.Exception.ToString()
                });
            }

            _logger.WriteInfo($"Rule succeeded with {result.ReturnValue ?? "no return value"}");
            return(new RuleResult()
            {
                Outcome = RuleExecutionOutcome.Success,
                Value = result.ReturnValue // ?? string.Empty
            });
        }