Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend the build server detection and reporting #1981

Merged
merged 1 commit into from
May 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using TechTalk.SpecFlow.Analytics;
using TechTalk.SpecFlow.Analytics.AppInsights;
using TechTalk.SpecFlow.Analytics.UserId;
using TechTalk.SpecFlow.EnvironmentAccess;
using TechTalk.SpecFlow.Generator.Project;

namespace SpecFlow.Tools.MsBuild.Generation
Expand Down Expand Up @@ -36,6 +37,7 @@ public IObjectContainer BuildRootContainer(
objectContainer.RegisterTypeAs<FileUserIdStore, IUserUniqueIdStore>();
objectContainer.RegisterTypeAs<FileService, IFileService>();
objectContainer.RegisterTypeAs<DirectoryService, IDirectoryService>();
objectContainer.RegisterTypeAs<EnvironmentWrapper, IEnvironmentWrapper>();

objectContainer.RegisterTypeAs<EnvironmentSpecFlowTelemetryChecker, IEnvironmentSpecFlowTelemetryChecker>();
objectContainer.RegisterTypeAs<AnalyticsTransmitter, IAnalyticsTransmitter>();
Expand Down
44 changes: 32 additions & 12 deletions TechTalk.SpecFlow/Analytics/AnalyticsEventProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@
using TechTalk.SpecFlow.Analytics.UserId;
using TechTalk.SpecFlow.UnitTestProvider;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using TechTalk.SpecFlow.EnvironmentAccess;
using TechTalk.SpecFlow.CommonModels;

namespace TechTalk.SpecFlow.Analytics
{
public class AnalyticsEventProvider : IAnalyticsEventProvider
{
private readonly IUserUniqueIdStore _userUniqueIdStore;
private readonly IEnvironmentWrapper _environmentWrapper;
private readonly string _unitTestProvider;

public AnalyticsEventProvider(IUserUniqueIdStore userUniqueIdStore, UnitTestProviderConfiguration unitTestProviderConfiguration)
public AnalyticsEventProvider(IUserUniqueIdStore userUniqueIdStore, UnitTestProviderConfiguration unitTestProviderConfiguration, IEnvironmentWrapper environmentWrapper)
{
_userUniqueIdStore = userUniqueIdStore;
_environmentWrapper = environmentWrapper;
_unitTestProvider = unitTestProviderConfiguration.UnitTestProvider;
}

Expand All @@ -23,7 +28,7 @@ public SpecFlowProjectCompilingEvent CreateProjectCompilingEvent(string msbuildV
string userId = _userUniqueIdStore.GetUserId();
string unitTestProvider = _unitTestProvider;
string specFlowVersion = GetSpecFlowVersion();
bool isBuildServer = IsBuildServerMode();
string buildServerName = GetBuildServerName();
bool isDockerContainer = IsRunningInDockerContainer();
string hashedAssemblyName = ToSha256(assemblyName);
string platform = GetOSPlatform();
Expand All @@ -36,7 +41,7 @@ public SpecFlowProjectCompilingEvent CreateProjectCompilingEvent(string msbuildV
platformDescription,
specFlowVersion,
unitTestProvider,
isBuildServer,
buildServerName,
hashedAssemblyName,
targetFrameworks,
targetFramework,
Expand All @@ -52,10 +57,10 @@ public SpecFlowProjectRunningEvent CreateProjectRunningEvent(string testAssembly
string userId = _userUniqueIdStore.GetUserId();
string unitTestProvider = _unitTestProvider;
string specFlowVersion = GetSpecFlowVersion();
bool isBuildServer = IsBuildServerMode();
string targetFramework = GetNetCoreVersion() ?? Environment.Version.ToString();
bool isDockerContainer = IsRunningInDockerContainer();

string buildServerName = GetBuildServerName();

string hashedAssemblyName = ToSha256(testAssemblyName);
string platform = GetOSPlatform();
string platformDescription = RuntimeInformation.OSDescription;
Expand All @@ -67,7 +72,7 @@ public SpecFlowProjectRunningEvent CreateProjectRunningEvent(string testAssembly
platformDescription,
specFlowVersion,
unitTestProvider,
isBuildServer,
buildServerName,
hashedAssemblyName,
null,
targetFramework,
Expand Down Expand Up @@ -95,17 +100,32 @@ private string GetOSPlatform()
throw new InvalidOperationException("Platform cannot be identified");
}

private bool IsBuildServerMode()
private readonly Dictionary<string, string> buildServerTypes
= new Dictionary<string, string> {
{ "TF_BUILD","Azure Pipelines"},
{ "TEAMCITY_VERSION","TeamCity"},
{ "JENKINS_HOME","Jenkins"},
{ "GITHUB_ACTIONS","GitHub Actions"},
{ "GITLAB_CI","GitLab CI/CD"},
{ "CODEBUILD_BUILD_ID","AWS CodeBuild"},
{ "TRAVIS","Travis CI"},
{ "APPVEYOR","AppVeyor"},
};

private string GetBuildServerName()
{
bool isRunByTfs = !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TF_BUILD"));
bool isRunByTeamCity = !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("TEAMCITY_VERSION"));

return isRunByTfs || isRunByTeamCity;
foreach (var buildServerType in buildServerTypes)
{
var envVariable = _environmentWrapper.GetEnvironmentVariable(buildServerType.Key);
if (envVariable is ISuccess<string>)
return buildServerType.Value;
}
return null;
}

private bool IsRunningInDockerContainer()
{
return !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER"));
return _environmentWrapper.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") is ISuccess<string>;
}

private string GetSpecFlowVersion()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public AppInsightsEventTelemetry(IAnalyticsEvent analyticsEvent)
{ "SpecFlowVersion", analyticsEvent.SpecFlowVersion },
{ "UnitTestProvider", analyticsEvent.UnitTestProvider ?? DefaultValue },
{ "IsBuildServer", analyticsEvent.IsBuildServer.ToString() },
{ "BuildServerName", analyticsEvent.BuildServerName ?? DefaultValue },
{ "IsDockerContainer", analyticsEvent.IsDockerContainer.ToString() },
{ "HashedAssemblyName", analyticsEvent.HashedAssemblyName ?? DefaultValue },
{ "TargetFrameworks", analyticsEvent.TargetFrameworks },
Expand Down
1 change: 1 addition & 0 deletions TechTalk.SpecFlow/Analytics/IAnalyticsEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public interface IAnalyticsEvent
string SpecFlowVersion { get; }
string UnitTestProvider { get; }
bool IsBuildServer { get; }
string BuildServerName { get; }
bool IsDockerContainer { get; }
string HashedAssemblyName { get;}
string TargetFrameworks { get; }
Expand Down
6 changes: 4 additions & 2 deletions TechTalk.SpecFlow/Analytics/SpecFlowAnalyticsEventBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,22 @@ public abstract class SpecFlowAnalyticsEventBase : IAnalyticsEvent
public string SpecFlowVersion { get; }
public string UnitTestProvider { get; }
public bool IsBuildServer { get; }
public string BuildServerName { get; }
public string HashedAssemblyName { get; }
public string TargetFrameworks { get; }
public string TargetFramework { get; }
public bool IsDockerContainer { get; }

protected SpecFlowAnalyticsEventBase(DateTime utcDate, string userId, string platform, string platformDescription, string specFlowVersion, string unitTestProvider, bool isBuildServer, string hashedAssemblyName, string targetFrameworks, string targetFramework, bool isDockerContainer)
protected SpecFlowAnalyticsEventBase(DateTime utcDate, string userId, string platform, string platformDescription, string specFlowVersion, string unitTestProvider, string buildServerName, string hashedAssemblyName, string targetFrameworks, string targetFramework, bool isDockerContainer)
{
UtcDate = utcDate;
UserId = userId;
Platform = platform;
PlatformDescription = platformDescription;
SpecFlowVersion = specFlowVersion;
UnitTestProvider = unitTestProvider;
IsBuildServer = isBuildServer;
BuildServerName = buildServerName;
IsBuildServer = !string.IsNullOrWhiteSpace(buildServerName);
HashedAssemblyName = hashedAssemblyName;
TargetFrameworks = targetFrameworks;
TargetFramework = targetFramework;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class SpecFlowProjectCompilingEvent : SpecFlowAnalyticsEventBase
public string MSBuildVersion { get; }
public string ProjectGuid { get; set; }

public SpecFlowProjectCompilingEvent(DateTime utcDate, string userId, string platform, string platformDescription, string specFlowVersion, string unitTestProvider, bool isBuildServer, string hashedAssemblyName, string targetFrameworks, string targetFramework, string msBuildVersion, string projectGuid, bool isDockerContainer) : base(utcDate, userId, platform, platformDescription, specFlowVersion, unitTestProvider, isBuildServer, hashedAssemblyName, targetFrameworks, targetFramework, isDockerContainer)
public SpecFlowProjectCompilingEvent(DateTime utcDate, string userId, string platform, string platformDescription, string specFlowVersion, string unitTestProvider, string buildServerName, string hashedAssemblyName, string targetFrameworks, string targetFramework, string msBuildVersion, string projectGuid, bool isDockerContainer) : base(utcDate, userId, platform, platformDescription, specFlowVersion, unitTestProvider, buildServerName, hashedAssemblyName, targetFrameworks, targetFramework, isDockerContainer)
{
MSBuildVersion = msBuildVersion;
ProjectGuid = projectGuid;
Expand Down
2 changes: 1 addition & 1 deletion TechTalk.SpecFlow/Analytics/SpecFlowProjectRunningEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace TechTalk.SpecFlow.Analytics
{
public class SpecFlowProjectRunningEvent : SpecFlowAnalyticsEventBase
{
public SpecFlowProjectRunningEvent(DateTime utcDate, string userId, string platform, string platformDescription, string specFlowVersion, string unitTestProvider, bool isBuildServer, string hashedAssemblyName, string targetFrameworks, string targetFramework, bool isDockerContainer) : base(utcDate, userId, platform, platformDescription, specFlowVersion, unitTestProvider, isBuildServer, hashedAssemblyName, targetFrameworks, targetFramework, isDockerContainer)
public SpecFlowProjectRunningEvent(DateTime utcDate, string userId, string platform, string platformDescription, string specFlowVersion, string unitTestProvider, string buildServerName, string hashedAssemblyName, string targetFrameworks, string targetFramework, bool isDockerContainer) : base(utcDate, userId, platform, platformDescription, specFlowVersion, unitTestProvider, buildServerName, hashedAssemblyName, targetFrameworks, targetFramework, isDockerContainer)
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using FluentAssertions;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechTalk.SpecFlow.Analytics;
using TechTalk.SpecFlow.Analytics.UserId;
using TechTalk.SpecFlow.CommonModels;
using TechTalk.SpecFlow.EnvironmentAccess;
using Xunit;

namespace TechTalk.SpecFlow.RuntimeTests.Analytics
{
public class AnalyticsEventProviderTests
{
[Fact]
public void Should_return_the_build_server_name_in_Compiling_Event()
{
var userUniqueIdStoreMock = new Mock<IUserUniqueIdStore>();
var environmentMock = new Mock<IEnvironmentWrapper>();
var sut = new AnalyticsEventProvider(userUniqueIdStoreMock.Object, new UnitTestProvider.UnitTestProviderConfiguration(), environmentMock.Object);

environmentMock
.Setup(m => m.GetEnvironmentVariable("TF_BUILD"))
.Returns(new Success<string>("true"));

var compilingEvent = sut.CreateProjectCompilingEvent(null, null, null, null, null);

compilingEvent.BuildServerName.Should().Be("Azure Pipelines");
}

[Fact]
public void Should_return_the_build_server_name_in_Running_Event()
{
var userUniqueIdStoreMock = new Mock<IUserUniqueIdStore>();
var environmentMock = new Mock<IEnvironmentWrapper>();
var sut = new AnalyticsEventProvider(userUniqueIdStoreMock.Object, new UnitTestProvider.UnitTestProviderConfiguration(), environmentMock.Object);

environmentMock
.Setup(m => m.GetEnvironmentVariable("TEAMCITY_VERSION"))
.Returns(new Success<string>("true"));

var compilingEvent = sut.CreateProjectRunningEvent(null);

compilingEvent.BuildServerName.Should().Be("TeamCity");
}

[Fact]
public void Should_return_null_for_the_build_server_name_when_not_detected()
{
var userUniqueIdStoreMock = new Mock<IUserUniqueIdStore>();
var environmentMock = new Mock<IEnvironmentWrapper>();
var sut = new AnalyticsEventProvider(userUniqueIdStoreMock.Object, new UnitTestProvider.UnitTestProviderConfiguration(), environmentMock.Object);

var compilingEvent = sut.CreateProjectRunningEvent(null);

compilingEvent.BuildServerName.Should().Be(null);
}
}
}