Source

TrafficLight / src / Core / Services / ProjectStatusResolvers / PulseProjectStatusResolverService.cs

using System.Net;
using CookComputing.XmlRpc;
using RossCode.TrafficLight.Core.Domain;

namespace RossCode.TrafficLight.Core.Services.ProjectStatusResolvers
{
    public class PulseProjectStatusResolverService : IProjectStatusResolverService
    {
        public BuildStatus CheckStatus(Project project)
        {
            var proxy = XmlRpcProxyGen.Create<IPulse>();
            proxy.Url = project.Url;

            var token = string.Empty;
            var buildStatus = BuildStatus.Unknown;
            try
            {
                token = proxy.Login(project.Username, project.Password);

                if (string.IsNullOrWhiteSpace(project.Name))
                {
                    var projectNames = proxy.GetProjectNames(token);

                    foreach (var projectName in projectNames)
                    {
                        var result = proxy.GetBuildFor(token, projectName, false);

                        var projectBuildStatus = GetBuildStatusFrom(result[0].status);

                        if (projectBuildStatus == BuildStatus.Building && buildStatus != BuildStatus.Failing)
                        {
                            buildStatus = BuildStatus.Building;
                            continue;
                        }

                        if (projectBuildStatus == BuildStatus.Success)
                        {
                            if (buildStatus == BuildStatus.Unknown)
                            {
                                buildStatus = BuildStatus.Success;
                            }
                            continue;
                        }

                        buildStatus = BuildStatus.Failing;
                    }
                }
                else
                {
                    var result = proxy.GetBuildFor(token, project.Name, false);
                    project.CurrentStatus = GetBuildStatusFrom(result[0].status);
                    buildStatus = project.CurrentStatus;
                }
            }
            catch (WebException)
            {
                // The server was likely unreachable for some reason (or perhaps a 404 or other error was returned.)
                buildStatus = BuildStatus.Unknown;
            }
            catch (XmlRpcIllFormedXmlException)
            {
                // The server was reachable, but the URL was likely invalid resulting in nonexistent or incorrect XML.
                buildStatus = BuildStatus.Unknown;
            }
            catch (XmlRpcFaultException)
            {
                // This can occur if the supplied credentials are missing or invalid.
                buildStatus = BuildStatus.Unknown;
            }
            finally
            {
                if (!string.IsNullOrEmpty(token))
                {
                    proxy.Logout(token);
                }
            }
            return buildStatus;
        }

        private BuildStatus GetBuildStatusFrom(string status)
        {
            switch (status.ToLower())
            {
                case "success":
                    return BuildStatus.Success;
                case "error":
                case "failure":
                    return BuildStatus.Failing;
                case "in progress":
                case "pending":
                case "terminating":
                    return BuildStatus.Building;
                default:
                    return BuildStatus.Unknown;
            }
        }
    }

    public interface IPulse : IXmlRpcProxy
    {
        [XmlRpcMethod("RemoteApi.login")]
        string Login(string username, string password);

        [XmlRpcMethod("RemoteApi.getLatestBuildForProject")]
        BuildResult[] GetBuildFor(string token, string projectName, bool completedOnly);

        [XmlRpcMethod("RemoteApi.logout")]
        bool Logout(string token);

        [XmlRpcMethod("RemoteApi.getAllProjectNames")]
        string[] GetProjectNames(string token);
    }

    public struct BuildResult
    {
        public string status { get; set; }
    }
}