/// <summary> /// Runs a named Pyphon script that uses the DSL /// </summary> /// <param name="scriptname">The python script file</param> /// <param name="IAzureDevOpsProvider">The Azure DevOps provider</param> /// <param name="iEmailProvider">The email provider</param> /// <param name="iEventdataProvider">The raw data provider</param> public void RunScript( string scriptname, IAzureDevOpsProvider iAzureDevOpsProvider, IEmailProvider iEmailProvider, IEventDataProvider iEventdataProvider) { this.RunScript( FolderHelper.GetRootedPath(@"dsl"), FolderHelper.GetRootedPath("~/"), scriptname, null, iAzureDevOpsProvider, iEmailProvider, iEventdataProvider); }
/// <summary> /// Runs a named Pyphon script that uses the DSL /// </summary> /// <param name="scriptname">The python script file</param> /// <param name="args">The parameters to pass to the script</param> /// <param name="IAzureDevOpsProvider">The Azure DevOps provider</param> /// <param name="iEmailProvider">The email provider</param> /// <param name="iEventdataProvider">The raw data provider</param> public void RunScript( string scriptname, Dictionary <string, object> args, IAzureDevOpsProvider iAzureDevOpsProvider, IEmailProvider iEmailProvider, IEventDataProvider iEventdataProvider) { this.RunScript( FolderHelper.GetRootedPath(@"dsl"), FolderHelper.GetRootedPath("~/"), scriptname, args, iAzureDevOpsProvider, iEmailProvider, iEventdataProvider); }
/// <summary> /// Test constructor /// </summary> /// <param name="iEmailProvider">Email provider</param> /// <param name="iAzureDevOpsProvider">Smpt Provider</param> /// <param name="scriptFile">The script file to run</param> /// <param name="dslFolder">Folder to scan for DSL assemblies</param> public WebHookController(IEmailProvider iEmailProvider, IAzureDevOpsProvider iAzureDevOpsProvider, string scriptFile, string dslFolder) { this.iEmailProvider = iEmailProvider; this.scriptFile = scriptFile; this.dslFolder = dslFolder; }
[Authorize] // Require some form of authentication public HttpResponseMessage Post([FromBody] JObject jsondata) { try { if (ConfigHelper.ParseOrDefault(Microsoft.Azure.CloudConfigurationManager.GetSetting("LogEventsToFile")) == true) { var logPath = ConfigHelper.GetLoggingPath(); logger.Info(string.Format("Post: Event being logged to [{0}]", logPath)); LoggingHelper.DumpEventToDisk(jsondata, logPath); } var dataProvider = new Providers.JsonDataProvider(jsondata); var uri = dataProvider.GetServerUrl(); var locationpat = ConfigHelper.GetPersonalAccessToken(uri); logger.Info($"Post: Using a {uri}"); if (string.IsNullOrEmpty(locationpat.Item2) == false) { logger.Info($"Post: Using a PAT token and obtained from {locationpat.Item1}"); this.iAzureDevOpsProvider = new Providers.AzureDevOpsProvider(uri, locationpat.Item2); } else { logger.Info(string.Format("Post: Using default credentials and url {0}", uri)); this.iAzureDevOpsProvider = new Providers.AzureDevOpsProvider(uri); } // work out the event type var eventType = dataProvider.GetEventType(); // work out the subscription ID var subscriptionID = dataProvider.GetSubsriptionID(); string[] argItems = null; switch (eventType) { case "workitem.updated": case "workitem.created": case "workitem.deleted": case "workitem.restored": case "workitem.commented": var workItemId = dataProvider.GetWorkItemDetails().Id; if (workItemId > 0) { argItems = new[] { eventType, workItemId.ToString() }; logger.Info( string.Format("Post: {1} Event being processed for WI:{0}", workItemId, eventType)); } else { logger.Error( string.Format("Post: {0} Event cannot find workitem ID", eventType)); return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } break; case "build.complete": var buildDetails = dataProvider.GetBuildDetails(); argItems = new[] { eventType, buildDetails.Id.ToString() }; logger.Info(string.Format( "Post: Event being processed for Build:{0}", buildDetails.BuildUri)); break; case "ms.vss-release.deployment-approval-completed-event": case "ms.vss-release.deployment-approval-pending-event": case "ms.vss-release.deployment-completed-event": case "ms.vss-release.deployment-started-event": case "ms.vss-release.release-abandoned-event": case "ms.vss-release.release-created-event": var releaseDetails = dataProvider.GetReleaseDetails(); argItems = new[] { eventType, releaseDetails.Id.ToString() }; logger.Info(string.Format( "Post: Event being processed for Release:{0}", releaseDetails.Id)); break; case "tfvc.checkin": var checkInDetails = dataProvider.GetCheckInDetails(); argItems = new[] { eventType, checkInDetails.Changeset.ToString() }; logger.Info( string.Format( "Post: Event being processed for Checkin:{0}", checkInDetails.Changeset)); break; case "message.posted": var messagePostDetails = dataProvider.GetMessagePostDetails(); argItems = new[] { eventType, messagePostDetails.PostRoomId.ToString() }; logger.Info( string.Format( "Post: Event being processed for Meesage Post in Room:{0}", messagePostDetails.PostRoomId)); break; case "git.push": var pushDetails = dataProvider.GetPushDetails(); argItems = new[] { eventType, pushDetails.Repo, pushDetails.PushId.ToString() }; logger.Info( string.Format( "Post: Event being processed for Push:{0}", pushDetails.PushId)); break; case "git.pullrequest.created": case "git.pullrequest.merged": case "git.pullrequest.updated": var pullDetails = dataProvider.GetPullDetails(); argItems = new[] { eventType, pullDetails.Repo, pullDetails.PullId.ToString() }; logger.Info( string.Format( "Post: Event being processed for Pull:{0}", pullDetails.PullId)); break; default: logger.Info(string.Format("Post: Unhandled event cannot processed:{0}", eventType)); return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } var args = new Dictionary <string, object> { { "Arguments", argItems }, }; var engine = new AzureDevOpsEventsProcessor.Dsl.DslProcessor(redirectScriptEngineOutputtoLogging); engine.RunScript( this.dslFolder, this.scriptFolder, FolderHelper.GetScriptName( eventType, subscriptionID, this.scriptFile, this.useSubscriptionID), args, this.iAzureDevOpsProvider, this.iEmailProvider, dataProvider); return(new HttpResponseMessage(HttpStatusCode.OK)); } catch (Exception ex) { // using a global exception catch to make sure we don't block any threads LoggingHelper.DumpException(logger, ex); return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } }
/// <summary> /// Constructor for DSL library /// </summary> /// <param name="IAzureDevOpsProvider">The Azure DevOps provider</param> /// <param name="iEmailProvider">The Email provider</param> public DslLibrary(IAzureDevOpsProvider iAzureDevOpsProvider, IEmailProvider iEmailProvider) { this.TfsProvider = iAzureDevOpsProvider; this.EmailProvider = iEmailProvider; }
public void RunScript( string dslFolder, string scriptFolder, string scriptname, Dictionary <string, object> args, IAzureDevOpsProvider iAzureDevOpsProvider, IEmailProvider iEmailProvider, IEventDataProvider iEventData) { if (scriptname == null) { throw new ArgumentNullException("scriptname"); } else { if (string.IsNullOrEmpty(scriptFolder)) { scriptFolder = FolderHelper.GetRootedPath("~/"); } else { scriptFolder = FolderHelper.GetRootedPath(scriptFolder); } if (File.Exists(scriptname) == false) { // we have not been given a resolvable file name, so try appending the base path scriptname = Path.Combine(scriptFolder, scriptname); if (File.Exists(scriptname) == false) { this.logger.Error(string.Format("DslProcessor: DslProcessor cannot find script:{0}", scriptname)); return; } } } if (iEventData == null) { throw new ArgumentNullException("iEventData"); } if (iAzureDevOpsProvider == null) { throw new ArgumentNullException("iAzureDevOpsProvider"); } if (iEmailProvider == null) { throw new ArgumentNullException("iEmailProvider"); } if (string.IsNullOrEmpty(dslFolder)) { dslFolder = FolderHelper.GetRootedPath("~/"); } else { dslFolder = FolderHelper.GetRootedPath(dslFolder); } // load the DSL wrapper class via MEF //An aggregate catalog that combines multiple catalogs var catalog = new AggregateCatalog(); //Adds all the parts found in the same assembly as the Program class if (Directory.Exists(dslFolder)) { this.logger.Info( string.Format("DslProcessor: DslProcessor loading DSL from {0}", Path.GetFullPath(dslFolder))); catalog.Catalogs.Add(new DirectoryCatalog(dslFolder)); } else { this.logger.Error( string.Format("DslProcessor: DslProcessor cannot find DSL folder {0}", Path.GetFullPath(dslFolder))); return; } try { //Create the CompositionContainer with the parts in the catalog var container = new CompositionContainer(catalog); container.ComposeParts(this); } catch (CompositionException compositionException) { this.logger.Error(string.Format("DsLProcessor: {0}", compositionException.Message)); return; } catch (ReflectionTypeLoadException ex) { this.logger.Error(string.Format("DsLProcessor: {0}", ex.Message)); StringBuilder sb = new StringBuilder(); foreach (Exception exSub in ex.LoaderExceptions) { sb.AppendLine(exSub.Message); FileNotFoundException exFileNotFound = exSub as FileNotFoundException; if (exFileNotFound != null) { if (!string.IsNullOrEmpty(exFileNotFound.FusionLog)) { sb.AppendLine("Fusion Log:"); sb.AppendLine(exFileNotFound.FusionLog); } } sb.AppendLine(); } this.logger.Error(string.Format("DslProcessor: {0}", sb.ToString())); return; } this.logger.Info( string.Format("DslProcessor: DslProcessor found {0} DSL libraries", this.dslLibraries.Count())); if (this.dslLibraries.Any()) { // create the engine var engine = IronPython.Hosting.Python.CreateEngine(args); var objOps = engine.Operations; var scope = engine.CreateScope(); // inject the providers foreach (var item in this.dslLibraries) { item.EmailProvider = iEmailProvider; item.TfsProvider = iAzureDevOpsProvider; item.EventData = iEventData; item.ScriptFolder = scriptFolder; // Read in the methods foreach (string memberName in objOps.GetMemberNames(item)) { scope.SetVariable(memberName, objOps.GetMember(item, memberName)); } } if (this.redirectScriptEngineOutputtoLogging == true) { // redirect the console out opf the script to the nLog engine.Runtime.IO.SetOutput( new ConsoleRedirectStreamToNlog(LogLevel.Info, "PythonScriptConsole"), System.Text.Encoding.ASCII); engine.Runtime.IO.SetErrorOutput( new ConsoleRedirectStreamToNlog(LogLevel.Error, "PythonScriptError"), System.Text.Encoding.ASCII); } else { // this is only used in tests where the console is visible or being cpatured in another manner engine.Runtime.IO.RedirectToConsole(); } // run the script this.logger.Info(string.Format( "DslProcessor: DslProcessor running script:{0}", scriptname)); var script = engine.CreateScriptSourceFromFile(scriptname); script.Execute(scope); } else { this.logger.Error( string.Format("DslProcessor: DslProcessor cannot find DSL libraries in folder {0}", Path.GetFullPath(dslFolder))); return; } }