Skip to content

Commit

Permalink
Feature dependencies and UML support (#69)
Browse files Browse the repository at this point in the history
Two new features we're added in this release:

Navigate to dependent features from a particular feature. This is an alpha feature, which you can enable from the settings page.
Embed UML diagrams based on [nomnoml](http://www.nomnoml.com) to your feature description as an UML code block and they will be displayed in Augurk.
  • Loading branch information
jmezach authored and marktaling committed Oct 10, 2018
1 parent a1c3716 commit ca6a5be
Show file tree
Hide file tree
Showing 83 changed files with 1,180 additions and 72,103 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Expand Up @@ -232,4 +232,7 @@ _Pvt_Extensions
*.ini

# SpecFlow Generated Code
*.feature.cs
*.feature.cs

# LibMan libraries
src/Augurk/libs
3 changes: 2 additions & 1 deletion GitVersion.yml
@@ -1,4 +1,5 @@
next-version: 2.6.1
next-version: 2.7.0
mode: ContinuousDeployment
branches: {}
ignore:
sha: []
13 changes: 13 additions & 0 deletions azure-pipelines.yml
Expand Up @@ -34,8 +34,21 @@ steps:
inputs:
platform: '$(buildPlatform)'
configuration: '$(buildConfiguration)'
codeCoverageEnabled: True
otherConsoleOptions: '/platform:X64'

- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.SourcesDirectory)/deploy/Augurk.WebDeploy.zip
artifactName: webdeploy

- task: CopyFiles@2
inputs:
sourceFolder: $(Build.SourcesDirectory)/src/Augurk.Specifications
contents: "**/?(*.feature|*.md)"
targetFolder: $(Build.ArtifactStagingDirectory)/features

- task: PublishBuildArtifacts@1
inputs:
pathToPublish: $(Build.ArtifactStagingDirectory)/features
artifactName: features
2 changes: 2 additions & 0 deletions extLib/Dagre@0.4.6/dagre.min.js

Large diffs are not rendered by default.

9 changes: 3 additions & 6 deletions src/Augurk.Api/Augurk.Api.csproj
Expand Up @@ -49,16 +49,13 @@
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="Raven.Abstractions, Version=3.0.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
<HintPath>..\packages\RavenDB.Database.3.0.3690\lib\net45\Raven.Abstractions.dll</HintPath>
<Private>True</Private>
<HintPath>..\packages\RavenDB.Database.3.0.30182\lib\net45\Raven.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Raven.Client.Lightweight, Version=3.0.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
<HintPath>..\packages\RavenDB.Client.3.0.3690\lib\net45\Raven.Client.Lightweight.dll</HintPath>
<Private>True</Private>
<HintPath>..\packages\RavenDB.Client.3.0.30182\lib\net45\Raven.Client.Lightweight.dll</HintPath>
</Reference>
<Reference Include="Raven.Database, Version=3.0.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
<HintPath>..\packages\RavenDB.Database.3.0.3690\lib\net45\Raven.Database.dll</HintPath>
<Private>True</Private>
<HintPath>..\packages\RavenDB.Database.3.0.30182\lib\net45\Raven.Database.dll</HintPath>
</Reference>
<Reference Include="Swagger.Net, Version=8.3.14.202, Culture=neutral, PublicKeyToken=cd1bb07a5ac7c7bc, processorArchitecture=MSIL">
<HintPath>..\packages\Swagger-Net.8.3.14.202\lib\net45\Swagger.Net.dll</HintPath>
Expand Down
1 change: 0 additions & 1 deletion src/Augurk.Api/Controllers/V2/AugurkController.cs
Expand Up @@ -15,7 +15,6 @@
*/

using Augurk.Api.Managers;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Http;
using Augurk.Entities;
Expand Down
9 changes: 8 additions & 1 deletion src/Augurk.Api/Controllers/V2/DependencyController.cs
Expand Up @@ -30,7 +30,14 @@ public class DependencyController : ApiController
[HttpGet]
public Task<IEnumerable<FeatureGraph>> GetSystemWideDependencies()
{
return _dependencyManager.GetTopLevelFeatureGraphs();
return _dependencyManager.GetTopLevelFeatureGraphsAsync();
}

[Route("products/{productName}/features/{featureName}/versions/{version}")]
[HttpGet]
public Task<FeatureGraph> GetFeatureGraph(string productName, string featureName, string version)
{
return _dependencyManager.GetFeatureGraphAsync(productName, featureName, version);
}
}
}
3 changes: 3 additions & 0 deletions src/Augurk.Api/Managers/AnalysisReportManager.cs
Expand Up @@ -126,6 +126,9 @@ public async Task DeleteDbInvocationsAsync(string productName, string version)
new Raven.Abstractions.Data.IndexQuery()
{
Query = $"Product:{productName} AND Version:{version}"
}, new Raven.Abstractions.Data.BulkOperationOptions
{
AllowStale = true
}).WaitForCompletionAsync();
}
}
Expand Down
64 changes: 61 additions & 3 deletions src/Augurk.Api/Managers/DependencyManager.cs
Expand Up @@ -15,6 +15,7 @@
*/
using Augurk.Entities;
using Raven.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand All @@ -34,7 +35,7 @@ public class DependencyManager
/// A collection of <see cref="FeatureGraph"/> instances representing
/// the dependency graphs for the unparented features.
/// </returns>
public async Task<IEnumerable<FeatureGraph>> GetTopLevelFeatureGraphs()
public async Task<IEnumerable<FeatureGraph>> GetTopLevelFeatureGraphsAsync()
{
using (var session = Database.DocumentStore.OpenAsyncSession())
{
Expand All @@ -45,14 +46,14 @@ public async Task<IEnumerable<FeatureGraph>> GetTopLevelFeatureGraphs()
select new
{
Invocation = invocation,
Features = features.Where(f => f.DirectInvocationSignatures.Intersect(invocation.InvokedSignatures).Any()).ToList()
Features = features.Where(f => f.DirectInvocationSignatures != null && f.DirectInvocationSignatures.Intersect(invocation.InvokedSignatures).Any()).ToList()
}).ToList();

var featuresInvocations = (from feature in features
select new
{
Feature = feature,
Invocations = invocationFeatures.Where(i => feature.DirectInvocationSignatures.Contains(i.Invocation.Signature))
Invocations = invocationFeatures.Where(i => feature.DirectInvocationSignatures != null && feature.DirectInvocationSignatures.Contains(i.Invocation.Signature))
}).ToList();

var featureGraphs = new Dictionary<DbFeature, FeatureGraph>();
Expand All @@ -62,6 +63,7 @@ select new
{
FeatureName = feature.Feature.Title,
ProductName = feature.Feature.Product,
GroupName = feature.Feature.Group,
Tags = feature.Feature.Tags,
Version = feature.Feature.Version,
DependsOn = new List<FeatureGraph>()
Expand All @@ -82,5 +84,61 @@ select new
return unparentedGraphs;
}
}

public async Task<FeatureGraph> GetFeatureGraphAsync(string productName, string featureName, string version)
{
// Create the result variable
var result = new FeatureGraph();
result.ProductName = productName;
result.FeatureName = featureName;
result.Version = version;

// For now, just use all tree as a source
var trees = (await GetTopLevelFeatureGraphsAsync()).ToList();

trees.ForEach(tree => ExtractFeatureRelations(tree, result));

return result;
}

private void ExtractFeatureRelations(FeatureGraph node, FeatureGraph result)
{
if (node.DescribesSameFeature(result))
{
// If it is the first time we encounter ourselves, continue on
if (result.DependsOn.Count == 0)
{
foreach (var dependency in node.DependsOn)
{
result.DependsOn.Add(new FeatureGraph()
{
ProductName = dependency.ProductName,
FeatureName = dependency.FeatureName,
GroupName = dependency.GroupName,
Version = dependency.Version
});
}
}
// otherwise, return
else
{
return;
}
}

if(node.DependsOn.Any(dependency => dependency.DescribesSameFeature(result))
&& !result.Dependants.Any(dependant => dependant.DescribesSameFeature(node)))
{
result.Dependants.Add(new FeatureGraph()
{
ProductName = node.ProductName,
FeatureName = node.FeatureName,
GroupName = node.GroupName,
Version = node.Version
});
}

node.DependsOn.ForEach(dependency => ExtractFeatureRelations(dependency, result));
}
}
}
5 changes: 4 additions & 1 deletion src/Augurk.Api/Properties/AssemblyInfo.cs
@@ -1,4 +1,5 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
Expand All @@ -19,4 +20,6 @@
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c1b08b58-7b57-4a9c-b8ad-a8fa96237d94")]
[assembly: Guid("c1b08b58-7b57-4a9c-b8ad-a8fa96237d94")]

[assembly: InternalsVisibleTo("Augurk.Test")]
4 changes: 2 additions & 2 deletions src/Augurk.Api/packages.config
Expand Up @@ -9,8 +9,8 @@
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net45" />
<package id="NuGet.Versioning" version="3.4.3" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="RavenDB.Client" version="3.0.3690" targetFramework="net45" />
<package id="RavenDB.Database" version="3.0.3690" targetFramework="net45" />
<package id="RavenDB.Client" version="3.0.30182" targetFramework="net45" />
<package id="RavenDB.Database" version="3.0.30182" targetFramework="net45" />
<package id="Swagger-Net" version="8.3.14.202" targetFramework="net45" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net45" />
</packages>
14 changes: 13 additions & 1 deletion src/Augurk.Entities/FeatureGraph.cs
Expand Up @@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
using System;
using System.Collections.Generic;

namespace Augurk.Entities
Expand All @@ -23,10 +24,21 @@ public class FeatureGraph

public string ProductName { get; set; }

public string GroupName { get; set; }

public string Version { get; set; }

public IEnumerable<string> Tags { get; set; }

public List<FeatureGraph> DependsOn { get; set; }
public List<FeatureGraph> DependsOn { get; set; } = new List<FeatureGraph>();

public List<FeatureGraph> Dependants { get; set; } = new List<FeatureGraph>();

public bool DescribesSameFeature(FeatureGraph other)
{
return this.FeatureName.Equals(other.FeatureName, StringComparison.Ordinal) &&
this.ProductName.Equals(other.ProductName, StringComparison.Ordinal) &&
this.Version.Equals(other.Version, StringComparison.Ordinal);
}
}
}
17 changes: 15 additions & 2 deletions src/Augurk.Specifications/App.config
Expand Up @@ -3,8 +3,21 @@
<configSections>
<section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
</configSections>

<specFlow>
<unitTestProvider name="MsTest" />
<!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config -->
</specFlow>

<!-- For additional details on SpecFlow configuration options see http://go.specflow.org/doc-config --></specFlow>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
36 changes: 29 additions & 7 deletions src/Augurk.Specifications/Augurk.Specifications.csproj
Expand Up @@ -16,6 +16,8 @@
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -35,10 +37,15 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="TechTalk.SpecFlow, Version=2.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41, processorArchitecture=MSIL">
<HintPath>..\packages\SpecFlow.2.1.0\lib\net45\TechTalk.SpecFlow.dll</HintPath>
<Private>True</Private>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="TechTalk.SpecFlow, Version=2.4.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41, processorArchitecture=MSIL">
<HintPath>..\packages\SpecFlow.2.4.0\lib\net45\TechTalk.SpecFlow.dll</HintPath>
</Reference>
</ItemGroup>
<Choose>
Expand Down Expand Up @@ -77,6 +84,11 @@
<DesignTime>True</DesignTime>
<DependentUpon>NotImplementedTag.feature</DependentUpon>
</Compile>
<Compile Include="Gherkin\UML.feature.cs">
<DependentUpon>UML.feature</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Gherkin\ChildOfTag.feature.cs">
<DependentUpon>ChildOfTag.feature</DependentUpon>
Expand All @@ -100,7 +112,9 @@
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="Configuration\RetentionPolicy.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>RetentionPolicy.feature.cs</LastGenOutput>
Expand All @@ -122,11 +136,17 @@
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>ChildOfTag.feature.cs</LastGenOutput>
</None>
<None Include="packages.config" />
<None Include="Gherkin\UML.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>UML.feature.cs</LastGenOutput>
</None>
<None Include="Gherkin\ServerSideTags.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>ServerSideTags.feature.cs</LastGenOutput>
</None>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<None Include="Portal\Versioned Features\V1\Versioning1.0.feature">
<Generator>SpecFlowSingleFileGenerator</Generator>
<LastGenOutput>Versioning1.0.feature.cs</LastGenOutput>
Expand Down Expand Up @@ -159,13 +179,15 @@
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\SpecFlow.2.1.0\tools\TechTalk.SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.1.0\tools\TechTalk.SpecFlow.targets')" />
<Import Project="..\packages\SpecFlow.2.4.0\tools\TechTalk.SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.4.0\tools\TechTalk.SpecFlow.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\SpecFlow.2.1.0\tools\TechTalk.SpecFlow.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SpecFlow.2.1.0\tools\TechTalk.SpecFlow.targets'))" />
<Error Condition="!Exists('..\packages\SpecFlow.2.4.0\tools\TechTalk.SpecFlow.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SpecFlow.2.4.0\tools\TechTalk.SpecFlow.targets'))" />
<Error Condition="!Exists('..\packages\SpecFlow.2.4.0\build\SpecFlow.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\SpecFlow.2.4.0\build\SpecFlow.targets'))" />
</Target>
<Import Project="..\packages\SpecFlow.2.4.0\build\SpecFlow.targets" Condition="Exists('..\packages\SpecFlow.2.4.0\build\SpecFlow.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down

0 comments on commit ca6a5be

Please sign in to comment.