提交 b09b76f6 编写于 作者: J Jared Parsons

Initial code for BuildBoss

上级 5fc837cb
......@@ -353,6 +353,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServicesVisualStudio.Next",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualStudioTest.Next", "src\VisualStudio\Core\Test.Next\VisualStudioTest.Next.csproj", "{2E1658E2-5045-4F85-A64C-C0ECCD39F719}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildBoss", "src\Tools\BuildBoss\BuildBoss.csproj", "{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Compilers\Core\CommandLine\CommandLine.projitems*{06b26dcb-7a12-48ef-ae50-708593abd05f}*SharedItemsImports = 4
......@@ -3080,6 +3082,26 @@ Global
{2E1658E2-5045-4F85-A64C-C0ECCD39F719}.Release|x64.Build.0 = Release|Any CPU
{2E1658E2-5045-4F85-A64C-C0ECCD39F719}.Release|x86.ActiveCfg = Release|Any CPU
{2E1658E2-5045-4F85-A64C-C0ECCD39F719}.Release|x86.Build.0 = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|ARM.ActiveCfg = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|ARM.Build.0 = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|x64.ActiveCfg = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|x64.Build.0 = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|x86.ActiveCfg = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|x86.Build.0 = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|Any CPU.Build.0 = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|ARM.ActiveCfg = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|ARM.Build.0 = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|x64.ActiveCfg = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|x64.Build.0 = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|x86.ActiveCfg = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......@@ -3245,5 +3267,6 @@ Global
{7259740A-FD0E-480F-A7D4-08BE90AC9051} = {8DBA5174-B0AA-4561-82B1-A46607697753}
{FE0D4BDD-1C30-488E-A870-854F5B8C5014} = {8DBA5174-B0AA-4561-82B1-A46607697753}
{2E1658E2-5045-4F85-A64C-C0ECCD39F719} = {8DBA5174-B0AA-4561-82B1-A46607697753}
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10} = {FD0FAF5F-1DED-485C-99FA-84B97F3A8EEC}
EndGlobalSection
EndGlobal
......@@ -121,6 +121,10 @@ REM Verify the state of our project.jsons
echo Running RepoUtil
.\Binaries\%BuildConfiguration%\Tools\RepoUtil\RepoUtil.exe verify || goto :BuildFailed
REM Verify the state of our project.jsons
echo Running BuildBoss
.\Binaries\%BuildConfiguration%\Exes\BuildBoss\BuildBoss.exe "%RoslynRoot%" || goto :BuildFailed
REM Ensure caller sees successful exit.
exit /b 0
......
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
</configuration>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\build\Targets\VSL.Settings.targets" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>BuildBoss</RootNamespace>
<AssemblyName>BuildBoss</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<UseVSHostingProcess>false</UseVSHostingProcess>
<TargetFrameworkProfile />
<RoslynProjectType>ExeDesktop</RoslynProjectType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " />
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " />
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="BuildBossConfig.cs" />
<Compile Include="Program.cs" />
<Compile Include="ProjectType.cs" />
<Compile Include="ProjectUtil.cs" />
<Compile Include="SharedUtil.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="..\..\..\build\Targets\VSL.Imports.targets" />
</Project>

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuildBoss", "BuildBoss.csproj", "{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RepoUtil", "..\RepoUtil\RepoUtil.csproj", "{1CA184D3-89CB-4074-BEC5-F8AEBA657D41}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C0660D9-48CA-40E1-BABA-8F6A1F11FE10}.Release|Any CPU.Build.0 = Release|Any CPU
{1CA184D3-89CB-4074-BEC5-F8AEBA657D41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1CA184D3-89CB-4074-BEC5-F8AEBA657D41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1CA184D3-89CB-4074-BEC5-F8AEBA657D41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1CA184D3-89CB-4074-BEC5-F8AEBA657D41}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BuildBoss
{
public sealed class BuildBossConfig
{
/// <summary>
/// The set of projects and paths to exclude.
/// </summary>
[JsonProperty(PropertyName = "exclude")]
public string[] Exclude { get; set; }
}
}
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace BuildBoss
{
internal static class Program
{
internal static int Main(string[] args)
{
var sourceDir = args[0];
var configPath = Path.Combine(sourceDir, @"build\config\BuildBossData.json");
var config = JsonConvert.DeserializeObject<BuildBossConfig>(File.ReadAllText(configPath));
var allGood = true;
var list = new List<string>();
foreach (var projectPath in Directory.EnumerateFiles(Path.Combine(sourceDir, "src"), "*proj", SearchOption.AllDirectories))
{
var doc = XDocument.Load(projectPath);
var relativePath = GetRelativePath(sourceDir, projectPath);
var projectType = GetProjectType(projectPath);
var util = new ProjectUtil(projectType, projectPath, doc);
var textWriter = new StringWriter();
if (!util.CheckAll(textWriter))
{
Console.WriteLine($"Checking {relativePath} failed");
Console.WriteLine(textWriter.ToString());
list.Add(relativePath);
allGood = false;
}
}
// Print it all out in the end for easy editting.
foreach (var item in list)
{
Console.WriteLine(item);
}
return allGood ? 0 : 1;
}
private static ProjectType GetProjectType(string path)
{
switch (Path.GetExtension(path))
{
case ".csproj": return ProjectType.CSharp;
case ".vbproj": return ProjectType.Basic;
case ".shproj": return ProjectType.Shared;
default:
return ProjectType.Unknown;
}
}
private static string GetRelativePath(string basePath, string fullPath)
{
if (!fullPath.StartsWith(basePath, StringComparison.OrdinalIgnoreCase))
{
throw new Exception($"{fullPath} doesn't begin with {basePath}");
}
return fullPath.Substring(basePath.Length + 1);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BuildBoss
{
internal enum ProjectType
{
CSharp,
Basic,
Shared,
Unknown
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
namespace BuildBoss
{
internal sealed class ProjectUtil
{
private readonly XDocument _projectData;
private readonly XmlNamespaceManager _manager;
internal ProjectType ProjectType { get; }
internal string ProjectFilePath { get; }
internal ProjectUtil(ProjectType projectType, string projectFilePath, XDocument projectData)
{
ProjectType = projectType;
ProjectFilePath = projectFilePath;
_projectData = projectData;
_manager = new XmlNamespaceManager(new NameTable());
_manager.AddNamespace("mb", SharedUtil.MSBuildNamespaceUriRaw);
}
internal bool CheckAll(TextWriter textWriter)
{
var allGood = true;
if (ProjectType == ProjectType.CSharp || ProjectType == ProjectType.Basic)
{
allGood &= CheckRestorePackages(textWriter);
}
return allGood;
}
private bool CheckRestorePackages(TextWriter textWriter)
{
var groups = _projectData.XPathSelectElements("//mb:PropertyGroup", _manager);
foreach(var group in groups)
{
foreach (var element in group.Elements())
{
if (element.Name.LocalName == "RestorePackages")
{
textWriter.WriteLine($"\tDo not use RestorePackages");
return false;
}
}
}
return true;
}
}
}
# RepoUtil
## Usage
This is a tool used to manage the inputs and outputs of our repo. In particular, it is used to manage our use of NuGet packages. It helps to automate the otherwise tedious process of updating NuGet references by:
- Fixing up project.json files
- Generating helper files with specified package versions. Example [Dependencies.props](https://github.com/dotnet/roslyn/blob/master/build/Targets/Dependencies.props)
The tool works by using all of our project.json files as the primary source of truth for the repo. All files with the name pattern `*project.json` are considered to be NuGet assets and will be scanned for NuGet references.
This will impose a minimum of requirements on our NuGet packages. In particular the tool assumes that all references to a given NuGet package should occur at the same version. If the tool sees a package being used with different versions it will issue an error.
There are valid cases where a package is used at more than one version in the repo. Typically because it's being deployed as an asset, used as a tool, etc ... In those cases an entry can be added to [RepoData.json](https://github.com/dotnet/roslyn/blob/master/src/Tools/RepoUtil/RepoData.json)) in the fixed table to call out that usage:
``` json
"fixed" {
"Microsoft.VSSDK.BuildTools": [ "14.3.25407", "15.0.25201-Dev15Preview2" ]
}
```
## Commands
This tool operates by having a set of sub commands that it executes
### change
The `change` command has two main purposes:
1. Update a NuGet package reference to a new version
2. Regenerate all of the supporting files
In order to change a single reference simply pass the new package as an argument:
``` cmd
RepoUtil change "System.Collections.Immutable 1.3.0"
```
For large number of packages a file can be used to list out all of the packages.
``` cmd
RepoUtil change -version e:\path\to\file.txt
```
To regenerate all of the supporting files without updating any packages just use `change` without any arguments
``` cmd
RepoUtil change
```
### verify
The `verify` command will simply analyze the state of the repo and ensure all of the NuGet dependencies are up to date:
- All packages are referenced at the same version.
- All the generated files are up to date.
- etc ...
All packages must fall into one of the following categories:
- Normal: Packages which are expected to be updated.
- Fixed: Package + version which are referenced at a version that should never change.
All uses of a normal package in the repo must have the same version. For example every use of System.Collections.Immutable.
An example of a normal package is System.Collections.Immutable. This package changes
### consumes
The `consumes` command produces a json file describing all of the NuGet packages consumed by the repo. It essentially aggregates all of the project.json files and adds a bit of metadata on top of them.
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace BuildBoss
{
internal static class SharedUtil
{
internal static string MSBuildNamespaceUriRaw => "http://schemas.microsoft.com/developer/msbuild/2003";
internal static Uri MSBuildNamespaceUri { get; } = new Uri(MSBuildNamespaceUriRaw);
internal static XNamespace MSBuildNamespace { get; } = XNamespace.Get(MSBuildNamespaceUriRaw);
internal static Encoding Encoding { get; } = Encoding.UTF8;
}
}
{
"supports": { },
"dependencies": {
"Newtonsoft.Json": "8.0.3",
"System.Collections.Immutable": "1.2.0"
},
"frameworks": {
".NETFramework,Version=v4.6": { }
},
"runtimes": {
"win": { },
"win7": { }
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册